diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..419ee8d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,8 @@ +module.exports = { + printWidth: 120, + bracketSpacing: true, + bracketSameLine: false, + semi: false, + singleQuote: true, + trailingComma: 'all', +} diff --git a/dist/index.js b/dist/index.js index 276f418..fac9a44 100644 --- a/dist/index.js +++ b/dist/index.js @@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.rules = void 0; const no_function_without_logging_1 = require("./rules/no-function-without-logging"); const rules = { - "no-function-without-logging": no_function_without_logging_1.default, + 'no-function-without-logging': no_function_without_logging_1.default, }; exports.rules = rules; diff --git a/dist/rules/no-function-without-logging.js b/dist/rules/no-function-without-logging.js index 8ed27e0..72cced4 100644 --- a/dist/rules/no-function-without-logging.js +++ b/dist/rules/no-function-without-logging.js @@ -3,20 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); const utils_1 = require("@typescript-eslint/utils"); const utils_2 = require("../utils"); -const createRule = utils_1.ESLintUtils.RuleCreator(() => "https://github.com/observation/eslint-rules"); +const createRule = utils_1.ESLintUtils.RuleCreator(() => 'https://github.com/observation/eslint-rules'); const createSuggestions = (blockStatement, suggestedLogging) => { - const logLevels = ["trace", "debug"]; + const logLevels = ['trace', 'debug']; return logLevels.map((logLevel) => { const suggestedCode = `Log.${logLevel}('${suggestedLogging}');`; return { - messageId: "addLoggingSuggestion", - data: { suggestedCode }, + messageId: 'addLoggingSuggestion', + data: { + suggestedCode, + }, fix: (fixer) => { if (blockStatement.body.length === 0) { - const newRange = [ - blockStatement.range[0] + 1, - blockStatement.range[1], - ]; + const newRange = [blockStatement.range[0] + 1, blockStatement.range[1]]; return fixer.insertTextBeforeRange(newRange, suggestedCode); } return fixer.insertTextBeforeRange(blockStatement.body[0].range, suggestedCode); @@ -27,16 +26,18 @@ const createSuggestions = (blockStatement, suggestedLogging) => { const addMissingLogStatementSuggestions = (context, node, blockStatement, correctLogging) => { context.report({ node, - messageId: "missingLogging", + messageId: 'missingLogging', suggest: createSuggestions(blockStatement, correctLogging), }); }; const getFunctionName = (node) => { - if (!node) + if (!node) { return null; + } if ((0, utils_2.isMethodDefinition)(node)) { - if ((0, utils_2.isIdentifier)(node.key)) + if ((0, utils_2.isIdentifier)(node.key)) { return node.key.name; + } } if ((0, utils_2.isFunctionDeclaration)(node)) { return node.id ? node.id.name : null; @@ -57,11 +58,11 @@ const getFunctionName = (node) => { } return getFunctionName(node.parent); }; -const traceLevels = ["debug", "trace", "info", "warning", "error"]; +const traceLevels = ['debug', 'trace', 'info', 'warning', 'error']; const isLogStatement = (expression) => { return ((0, utils_2.isMemberExpression)(expression.callee) && (0, utils_2.isIdentifier)(expression.callee.object) && - expression.callee.object.name === "Log" && + expression.callee.object.name === 'Log' && (0, utils_2.isIdentifier)(expression.callee.property) && traceLevels.includes(expression.callee.property.name)); }; @@ -77,7 +78,7 @@ const containsLoggingStatement = (blockStatement) => { return false; }; const checkFunctionDeclaration = (context, node) => { - const functionName = node.id ? node.id.name : ""; + const functionName = node.id ? node.id.name : ''; const file = path.parse(context.getFilename()); const correctLogging = `${file.name}:${functionName}`; if (!containsLoggingStatement(node.body)) { @@ -94,11 +95,13 @@ const checkCallExpression = (context, node) => { const newRange = [node.range[0], node.range[1] - 1]; context.report({ node, - messageId: "incorrectLogging", - data: { expectedLogging }, + messageId: 'incorrectLogging', + data: { + expectedLogging, + }, suggest: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', fix: (fixer) => { return fixer.insertTextAfterRange(newRange, `'${expectedLogging}'`); }, @@ -107,15 +110,17 @@ const checkCallExpression = (context, node) => { }); return; } - if ((0, utils_2.isLiteral)(argument) && typeof argument.value === "string") { + if ((0, utils_2.isLiteral)(argument) && typeof argument.value === 'string') { if (!argument.value.startsWith(expectedLogging)) { context.report({ node, - messageId: "incorrectLogging", - data: { expectedLogging }, + messageId: 'incorrectLogging', + data: { + expectedLogging, + }, suggest: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', fix: (fixer) => { return fixer.replaceTextRange(argument.range, `'${expectedLogging}'`); }, @@ -127,8 +132,9 @@ const checkCallExpression = (context, node) => { } }; const checkVariableDeclaration = (context, node) => { - if (node.declarations.length !== 1) + if (node.declarations.length !== 1) { return; + } const [declaration] = node.declarations; if (declaration.init && (0, utils_2.isArrowFunctionExpression)(declaration.init) && @@ -138,8 +144,9 @@ const checkVariableDeclaration = (context, node) => { const filename = path.parse(context.getFilename()).name; const functionName = declaration.id.name; const isComponentDeclaration = filename === functionName; - if (isComponentDeclaration) + if (isComponentDeclaration) { return; + } if (!containsLoggingStatement(body)) { const correctLogging = `${filename}:${functionName}`; addMissingLogStatementSuggestions(context, node, body, correctLogging); @@ -162,26 +169,29 @@ const checkPropertyDefinition = (context, node) => { }; const isSetterLikeMethodDefinition = (node, functionName) => { const { returnType } = node.value; - const returnsVoid = returnType === undefined || - returnType.typeAnnotation.type === "TSVoidKeyword"; - const startsWithSetterLikeName = new RegExp("^set[A-Z].*"); + const returnsVoid = returnType === undefined || returnType.typeAnnotation.type === 'TSVoidKeyword'; + const startsWithSetterLikeName = new RegExp('^set[A-Z].*'); const hasSetterLikeFunctionName = startsWithSetterLikeName.test(functionName); return hasSetterLikeFunctionName && returnsVoid; }; const checkMethodDefinition = (context, node) => { - if (node.kind === "constructor") + if (node.kind === 'constructor') { return; - if (node.kind === "get") + } + if (node.kind === 'get') { return; - if (node.kind === "set") + } + if (node.kind === 'set') { return; + } if ((0, utils_2.isFunctionExpression)(node.value) && (0, utils_2.isIdentifier)(node.key)) { const { body } = node.value; if (!containsLoggingStatement(body)) { const filename = path.parse(context.getFilename()).name; const functionName = node.key.name; - if (isSetterLikeMethodDefinition(node, functionName)) + if (isSetterLikeMethodDefinition(node, functionName)) { return; + } const correctLogging = filename === functionName ? filename : `${filename}:${functionName}`; addMissingLogStatementSuggestions(context, node, body, correctLogging); } @@ -197,19 +207,19 @@ const noFunctionWithoutLogging = createRule({ MethodDefinition: (node) => checkMethodDefinition(context, node), }; }, - name: "no-function-without-logging", + name: 'no-function-without-logging', meta: { docs: { - description: "All functions should include a logging statement", - recommended: "error", + description: 'All functions should include a logging statement', + recommended: 'error', }, messages: { incorrectLogging: "Logging should include the filename and function name: Log.debug('{{ expectedLogging }}')", - missingLogging: "Functions should include at least one logging statement", + missingLogging: 'Functions should include at least one logging statement', addLoggingSuggestion: "Add '{{ suggestedCode }}' at beginning of block statement", }, - type: "suggestion", - fixable: "code", + type: 'suggestion', + fixable: 'code', schema: [], hasSuggestions: true, }, diff --git a/src/index.ts b/src/index.ts index 146b36d..f2d5279 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ -import noFunctionWithoutLogging from "./rules/no-function-without-logging" +import noFunctionWithoutLogging from './rules/no-function-without-logging' const rules = { - "no-function-without-logging": noFunctionWithoutLogging, + 'no-function-without-logging': noFunctionWithoutLogging, } export { rules } diff --git a/src/rules/__tests__/no-function-without-logging.test.ts b/src/rules/__tests__/no-function-without-logging.test.ts index 9e54c20..791853a 100644 --- a/src/rules/__tests__/no-function-without-logging.test.ts +++ b/src/rules/__tests__/no-function-without-logging.test.ts @@ -1,236 +1,223 @@ -import { ESLintUtils } from "@typescript-eslint/utils" +import { ESLintUtils } from '@typescript-eslint/utils' -import noFunctionWithoutLogging from "../no-function-without-logging" +import noFunctionWithoutLogging from '../no-function-without-logging' const ruleTester = new ESLintUtils.RuleTester({ - parser: "@typescript-eslint/parser", + parser: '@typescript-eslint/parser', }) -ruleTester.run("no-function-without-logging", noFunctionWithoutLogging, { +ruleTester.run('no-function-without-logging', noFunctionWithoutLogging, { valid: [ { - name: "Function declaration", + name: 'Function declaration', code: "function functionName(){ Log.debug('file:functionName')}", }, { - name: "Function in variable declaration", + name: 'Function in variable declaration', code: "const functionName = () => { Log.debug('file:functionName') }", }, { - name: "Static function declaration", + name: 'Static function declaration', code: "static function functionName(){ Log.debug('file:functionName') }", }, { - name: "Function declaration in class", + name: 'Function declaration in class', code: "class ClassName { functionName(){ Log.debug('file:functionName') } }", }, { - name: "Function in variable declaration in class", + name: 'Function in variable declaration in class', code: "class ClassName { const functionName = () => { Log.debug('file:functionName') } }", }, { - name: "Class constructor does not need logging statement", - code: "class ClassName { constructor(){} }", + name: 'Class constructor does not need logging statement', + code: 'class ClassName { constructor(){} }', }, { - name: "Class getter does not need logging statement", - code: "class ClassName { get value(){} }", + name: 'Class getter does not need logging statement', + code: 'class ClassName { get value(){} }', }, { - name: "Class setter does not need logging statement", - code: "class ClassName { set value(value){} }", + name: 'Class setter does not need logging statement', + code: 'class ClassName { set value(value){} }', }, { name: "Setter like function (class method definition starting with 'set[A-Z]' returning void) does not need logging statement", - code: "class ClassName { setValue(value){} }", + code: 'class ClassName { setValue(value){} }', }, { - name: "Logging statement can include multiple arguments", + name: 'Logging statement can include multiple arguments', code: "function functionName(){ Log.debug('file:functionName', 1)}", }, { - name: "Logging statement can have extended text", + name: 'Logging statement can have extended text', code: "function functionName(){ Log.debug('file:functionName with extra text')}", }, { - name: "Lambda function with body does not need logging statement", - code: "const functionName = () => otherFunction()", + name: 'Lambda function with body does not need logging statement', + code: 'const functionName = () => otherFunction()', }, { - name: "Component declaration does not need logging statement", - filename: "Component", - code: "const Component = () => { }", + name: 'Component declaration does not need logging statement', + filename: 'Component', + code: 'const Component = () => { }', }, { - name: "Component level logging only includes component name", - filename: "Component", + name: 'Component level logging only includes component name', + filename: 'Component', code: "const Component = () => { Log.debug('Component') }", }, ], invalid: [ { - name: "Missing logging in function declaration", - code: "function functionName(){}", + name: 'Missing logging in function declaration', + code: 'function functionName(){}', errors: [ { - messageId: "missingLogging", - data: { expectedLogging: "file:functionName" }, + messageId: 'missingLogging', + data: { expectedLogging: 'file:functionName' }, suggestions: [ { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.trace('file:functionName');" }, - output: - "function functionName(){Log.trace('file:functionName');}", + output: "function functionName(){Log.trace('file:functionName');}", }, { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.debug('file:functionName');" }, - output: - "function functionName(){Log.debug('file:functionName');}", + output: "function functionName(){Log.debug('file:functionName');}", }, ], }, ], }, { - name: "Missing logging in function in variable declaration", - code: "const functionName = () => { }", + name: 'Missing logging in function in variable declaration', + code: 'const functionName = () => { }', errors: [ { - messageId: "missingLogging", - data: { expectedLogging: "file:functionName" }, + messageId: 'missingLogging', + data: { expectedLogging: 'file:functionName' }, suggestions: [ { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.trace('file:functionName');" }, - output: - "const functionName = () => {Log.trace('file:functionName'); }", + output: "const functionName = () => {Log.trace('file:functionName'); }", }, { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.debug('file:functionName');" }, - output: - "const functionName = () => {Log.debug('file:functionName'); }", + output: "const functionName = () => {Log.debug('file:functionName'); }", }, ], }, ], }, { - name: "Missing logging in static function declaration", - code: "static function functionName(){ }", + name: 'Missing logging in static function declaration', + code: 'static function functionName(){ }', errors: [ { - messageId: "missingLogging", - data: { expectedLogging: "file:functionName" }, + messageId: 'missingLogging', + data: { expectedLogging: 'file:functionName' }, suggestions: [ { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.trace('file:functionName');" }, - output: - "static function functionName(){Log.trace('file:functionName'); }", + output: "static function functionName(){Log.trace('file:functionName'); }", }, { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.debug('file:functionName');" }, - output: - "static function functionName(){Log.debug('file:functionName'); }", + output: "static function functionName(){Log.debug('file:functionName'); }", }, ], }, ], }, { - name: "Missing logging in class function", - code: "class ClassName { functionName(){ } }", + name: 'Missing logging in class function', + code: 'class ClassName { functionName(){ } }', errors: [ { - messageId: "missingLogging", - data: { expectedLogging: "file:functionName" }, + messageId: 'missingLogging', + data: { expectedLogging: 'file:functionName' }, suggestions: [ { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.trace('file:functionName');" }, - output: - "class ClassName { functionName(){Log.trace('file:functionName'); } }", + output: "class ClassName { functionName(){Log.trace('file:functionName'); } }", }, { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.debug('file:functionName');" }, - output: - "class ClassName { functionName(){Log.debug('file:functionName'); } }", + output: "class ClassName { functionName(){Log.debug('file:functionName'); } }", }, ], }, ], }, { - name: "Missing logging in function in class property", - code: "class ClassName { functionName = () => { } }", + name: 'Missing logging in function in class property', + code: 'class ClassName { functionName = () => { } }', errors: [ { - messageId: "missingLogging", - data: { expectedLogging: "file:functionName" }, + messageId: 'missingLogging', + data: { expectedLogging: 'file:functionName' }, suggestions: [ { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.trace('file:functionName');" }, - output: - "class ClassName { functionName = () => {Log.trace('file:functionName'); } }", + output: "class ClassName { functionName = () => {Log.trace('file:functionName'); } }", }, { - messageId: "addLoggingSuggestion", + messageId: 'addLoggingSuggestion', data: { suggestedCode: "Log.debug('file:functionName');" }, - output: - "class ClassName { functionName = () => {Log.debug('file:functionName'); } }", + output: "class ClassName { functionName = () => {Log.debug('file:functionName'); } }", }, ], }, ], }, { - name: "Missing function name in logging", + name: 'Missing function name in logging', code: "function functionName(){ Log.debug('file')}", errors: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', suggestions: [ { - messageId: "incorrectLogging", - output: - "function functionName(){ Log.debug('file:functionName')}", + messageId: 'incorrectLogging', + output: "function functionName(){ Log.debug('file:functionName')}", }, ], }, ], }, { - name: "Missing filename in logging", + name: 'Missing filename in logging', code: "function functionName(){ Log.debug('functionName')}", errors: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', suggestions: [ { - messageId: "incorrectLogging", - output: - "function functionName(){ Log.debug('file:functionName')}", + messageId: 'incorrectLogging', + output: "function functionName(){ Log.debug('file:functionName')}", }, ], }, ], }, { - name: "No arguments given to log statement", + name: 'No arguments given to log statement', code: `const functionName = () => { Log.debug() }`, errors: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', suggestions: [ { - messageId: "incorrectLogging", - output: - "const functionName = () => { Log.debug('file:functionName') }", + messageId: 'incorrectLogging', + output: "const functionName = () => { Log.debug('file:functionName') }", }, ], }, diff --git a/src/rules/no-function-without-logging.ts b/src/rules/no-function-without-logging.ts index 1e225bf..5285917 100644 --- a/src/rules/no-function-without-logging.ts +++ b/src/rules/no-function-without-logging.ts @@ -1,12 +1,8 @@ -import * as path from "path" +import * as path from 'path' -import { TSESTree } from "@typescript-eslint/utils" -import { ESLintUtils } from "@typescript-eslint/utils" -import { - ReportSuggestionArray, - RuleContext, - RuleFixer, -} from "@typescript-eslint/utils/dist/ts-eslint" +import { TSESTree } from '@typescript-eslint/utils' +import { ESLintUtils } from '@typescript-eslint/utils' +import { ReportSuggestionArray, RuleContext, RuleFixer } from '@typescript-eslint/utils/dist/ts-eslint' import { isArrowFunctionExpression, @@ -21,37 +17,31 @@ import { isMethodDefinition, isPropertyDefinition, isVariableDeclarator, -} from "../utils" +} from '../utils' -const createRule = ESLintUtils.RuleCreator( - () => "https://github.com/observation/eslint-rules" -) +const createRule = ESLintUtils.RuleCreator(() => 'https://github.com/observation/eslint-rules') -type messageIds = "incorrectLogging" | "missingLogging" | "addLoggingSuggestion" +type messageIds = 'incorrectLogging' | 'missingLogging' | 'addLoggingSuggestion' const createSuggestions = ( blockStatement: TSESTree.BlockStatement, - suggestedLogging: string -): ReportSuggestionArray<"addLoggingSuggestion"> => { - const logLevels = ["trace", "debug"] + suggestedLogging: string, +): ReportSuggestionArray<'addLoggingSuggestion'> => { + const logLevels = ['trace', 'debug'] return logLevels.map((logLevel) => { const suggestedCode = `Log.${logLevel}('${suggestedLogging}');` return { - messageId: "addLoggingSuggestion", - data: { suggestedCode }, + messageId: 'addLoggingSuggestion', + data: { + suggestedCode, + }, fix: (fixer: RuleFixer) => { if (blockStatement.body.length === 0) { - const newRange: TSESTree.Range = [ - blockStatement.range[0] + 1, - blockStatement.range[1], - ] + const newRange: TSESTree.Range = [blockStatement.range[0] + 1, blockStatement.range[1]] return fixer.insertTextBeforeRange(newRange, suggestedCode) } - return fixer.insertTextBeforeRange( - blockStatement.body[0].range, - suggestedCode - ) + return fixer.insertTextBeforeRange(blockStatement.body[0].range, suggestedCode) }, } }) @@ -61,20 +51,24 @@ const addMissingLogStatementSuggestions = ( context: Readonly>, node: TSESTree.Node, blockStatement: TSESTree.BlockStatement, - correctLogging: string + correctLogging: string, ) => { context.report({ node, - messageId: "missingLogging", + messageId: 'missingLogging', suggest: createSuggestions(blockStatement, correctLogging), }) } const getFunctionName = (node?: TSESTree.Node): string | null => { - if (!node) return null + if (!node) { + return null + } if (isMethodDefinition(node)) { - if (isIdentifier(node.key)) return node.key.name + if (isIdentifier(node.key)) { + return node.key.name + } } if (isFunctionDeclaration(node)) { @@ -100,21 +94,19 @@ const getFunctionName = (node?: TSESTree.Node): string | null => { return getFunctionName(node.parent) } -const traceLevels = ["debug", "trace", "info", "warning", "error"] +const traceLevels = ['debug', 'trace', 'info', 'warning', 'error'] const isLogStatement = (expression: TSESTree.CallExpression) => { return ( isMemberExpression(expression.callee) && isIdentifier(expression.callee.object) && - expression.callee.object.name === "Log" && + expression.callee.object.name === 'Log' && isIdentifier(expression.callee.property) && traceLevels.includes(expression.callee.property.name) ) } -const containsLoggingStatement = ( - blockStatement: TSESTree.BlockStatement -): boolean => { +const containsLoggingStatement = (blockStatement: TSESTree.BlockStatement): boolean => { for (var statement of blockStatement.body) { if (isExpressionStatement(statement)) { const { expression } = statement @@ -130,9 +122,9 @@ const containsLoggingStatement = ( const checkFunctionDeclaration = ( context: Readonly>, - node: TSESTree.FunctionDeclaration + node: TSESTree.FunctionDeclaration, ) => { - const functionName = node.id ? node.id.name : "" + const functionName = node.id ? node.id.name : '' const file = path.parse(context.getFilename()) const correctLogging = `${file.name}:${functionName}` @@ -141,31 +133,26 @@ const checkFunctionDeclaration = ( } } -const checkCallExpression = ( - context: Readonly>, - node: TSESTree.CallExpression -) => { +const checkCallExpression = (context: Readonly>, node: TSESTree.CallExpression) => { if (isLogStatement(node)) { const filename = path.parse(context.getFilename()).name const functionName = getFunctionName(node) - const expectedLogging = - filename === functionName ? filename : `${filename}:${functionName}` + const expectedLogging = filename === functionName ? filename : `${filename}:${functionName}` const [argument] = node.arguments if (!argument) { const newRange: TSESTree.Range = [node.range[0], node.range[1] - 1] context.report({ node, - messageId: "incorrectLogging", - data: { expectedLogging }, + messageId: 'incorrectLogging', + data: { + expectedLogging, + }, suggest: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', fix: (fixer) => { - return fixer.insertTextAfterRange( - newRange, - `'${expectedLogging}'` - ) + return fixer.insertTextAfterRange(newRange, `'${expectedLogging}'`) }, }, ], @@ -173,20 +160,19 @@ const checkCallExpression = ( return } - if (isLiteral(argument) && typeof argument.value === "string") { + if (isLiteral(argument) && typeof argument.value === 'string') { if (!argument.value.startsWith(expectedLogging)) { context.report({ node, - messageId: "incorrectLogging", - data: { expectedLogging }, + messageId: 'incorrectLogging', + data: { + expectedLogging, + }, suggest: [ { - messageId: "incorrectLogging", + messageId: 'incorrectLogging', fix: (fixer) => { - return fixer.replaceTextRange( - argument.range, - `'${expectedLogging}'` - ) + return fixer.replaceTextRange(argument.range, `'${expectedLogging}'`) }, }, ], @@ -198,9 +184,11 @@ const checkCallExpression = ( const checkVariableDeclaration = ( context: Readonly>, - node: TSESTree.VariableDeclaration + node: TSESTree.VariableDeclaration, ) => { - if (node.declarations.length !== 1) return + if (node.declarations.length !== 1) { + return + } const [declaration] = node.declarations if ( @@ -215,7 +203,9 @@ const checkVariableDeclaration = ( const functionName = declaration.id.name const isComponentDeclaration = filename === functionName - if (isComponentDeclaration) return + if (isComponentDeclaration) { + return + } if (!containsLoggingStatement(body)) { const correctLogging = `${filename}:${functionName}` @@ -226,7 +216,7 @@ const checkVariableDeclaration = ( const checkPropertyDefinition = ( context: Readonly>, - node: TSESTree.PropertyDefinition + node: TSESTree.PropertyDefinition, ) => { if ( node.value && @@ -239,35 +229,32 @@ const checkPropertyDefinition = ( if (!containsLoggingStatement(body)) { const filename = path.parse(context.getFilename()).name const functionName = node.key.name - const correctLogging = - filename === functionName ? filename : `${filename}:${functionName}` + const correctLogging = filename === functionName ? filename : `${filename}:${functionName}` addMissingLogStatementSuggestions(context, node, body, correctLogging) } } } -const isSetterLikeMethodDefinition = ( - node: TSESTree.MethodDefinition, - functionName: string -) => { +const isSetterLikeMethodDefinition = (node: TSESTree.MethodDefinition, functionName: string) => { const { returnType } = node.value - const returnsVoid = - returnType === undefined || - returnType.typeAnnotation.type === "TSVoidKeyword" + const returnsVoid = returnType === undefined || returnType.typeAnnotation.type === 'TSVoidKeyword' - const startsWithSetterLikeName = new RegExp("^set[A-Z].*") + const startsWithSetterLikeName = new RegExp('^set[A-Z].*') const hasSetterLikeFunctionName = startsWithSetterLikeName.test(functionName) return hasSetterLikeFunctionName && returnsVoid } -const checkMethodDefinition = ( - context: Readonly>, - node: TSESTree.MethodDefinition -) => { - if (node.kind === "constructor") return - if (node.kind === "get") return - if (node.kind === "set") return +const checkMethodDefinition = (context: Readonly>, node: TSESTree.MethodDefinition) => { + if (node.kind === 'constructor') { + return + } + if (node.kind === 'get') { + return + } + if (node.kind === 'set') { + return + } if (isFunctionExpression(node.value) && isIdentifier(node.key)) { const { body } = node.value @@ -275,10 +262,11 @@ const checkMethodDefinition = ( const filename = path.parse(context.getFilename()).name const functionName = node.key.name - if (isSetterLikeMethodDefinition(node, functionName)) return + if (isSetterLikeMethodDefinition(node, functionName)) { + return + } - const correctLogging = - filename === functionName ? filename : `${filename}:${functionName}` + const correctLogging = filename === functionName ? filename : `${filename}:${functionName}` addMissingLogStatementSuggestions(context, node, body, correctLogging) } } @@ -294,21 +282,19 @@ const noFunctionWithoutLogging = createRule({ MethodDefinition: (node) => checkMethodDefinition(context, node), } }, - name: "no-function-without-logging", + name: 'no-function-without-logging', meta: { docs: { - description: "All functions should include a logging statement", - recommended: "error", + description: 'All functions should include a logging statement', + recommended: 'error', }, messages: { - incorrectLogging: - "Logging should include the filename and function name: Log.debug('{{ expectedLogging }}')", - missingLogging: "Functions should include at least one logging statement", - addLoggingSuggestion: - "Add '{{ suggestedCode }}' at beginning of block statement", + incorrectLogging: "Logging should include the filename and function name: Log.debug('{{ expectedLogging }}')", + missingLogging: 'Functions should include at least one logging statement', + addLoggingSuggestion: "Add '{{ suggestedCode }}' at beginning of block statement", }, - type: "suggestion", - fixable: "code", + type: 'suggestion', + fixable: 'code', schema: [], hasSuggestions: true, }, diff --git a/src/utils.ts b/src/utils.ts index 6bd5cab..4d3b656 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,79 +1,53 @@ -import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils" +import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils' -export const isCallExpression = ( - statement: TSESTree.Node -): statement is TSESTree.CallExpression => { +export const isCallExpression = (statement: TSESTree.Node): statement is TSESTree.CallExpression => { return statement.type === AST_NODE_TYPES.CallExpression } -export const isMemberExpression = ( - statement: TSESTree.Node -): statement is TSESTree.MemberExpression => { +export const isMemberExpression = (statement: TSESTree.Node): statement is TSESTree.MemberExpression => { return statement.type === AST_NODE_TYPES.MemberExpression } -export const isIdentifier = ( - statement: TSESTree.Node -): statement is TSESTree.Identifier => { +export const isIdentifier = (statement: TSESTree.Node): statement is TSESTree.Identifier => { return statement.type === AST_NODE_TYPES.Identifier } -export const isExpressionStatement = ( - statement: TSESTree.Node -): statement is TSESTree.ExpressionStatement => { +export const isExpressionStatement = (statement: TSESTree.Node): statement is TSESTree.ExpressionStatement => { return statement.type === AST_NODE_TYPES.ExpressionStatement } -export const isLiteral = ( - statement: TSESTree.Node -): statement is TSESTree.Literal => { +export const isLiteral = (statement: TSESTree.Node): statement is TSESTree.Literal => { return statement.type === AST_NODE_TYPES.Literal } -export const isMethodDefinition = ( - statement: TSESTree.Node -): statement is TSESTree.MethodDefinition => { +export const isMethodDefinition = (statement: TSESTree.Node): statement is TSESTree.MethodDefinition => { return statement.type === AST_NODE_TYPES.MethodDefinition } -export const isArrowFunctionExpression = ( - statement: TSESTree.Node -): statement is TSESTree.ArrowFunctionExpression => { +export const isArrowFunctionExpression = (statement: TSESTree.Node): statement is TSESTree.ArrowFunctionExpression => { return statement.type === AST_NODE_TYPES.ArrowFunctionExpression } -export const isBlockStatement = ( - statement: TSESTree.Node -): statement is TSESTree.BlockStatement => { +export const isBlockStatement = (statement: TSESTree.Node): statement is TSESTree.BlockStatement => { return statement.type === AST_NODE_TYPES.BlockStatement } -export const isFunctionDeclaration = ( - statement: TSESTree.Node -): statement is TSESTree.FunctionDeclaration => { +export const isFunctionDeclaration = (statement: TSESTree.Node): statement is TSESTree.FunctionDeclaration => { return statement.type === AST_NODE_TYPES.FunctionDeclaration } -export const isPropertyDefinition = ( - statement: TSESTree.Node -): statement is TSESTree.PropertyDefinition => { +export const isPropertyDefinition = (statement: TSESTree.Node): statement is TSESTree.PropertyDefinition => { return statement.type === AST_NODE_TYPES.PropertyDefinition } -export const isVariableDeclaration = ( - statement: TSESTree.Node -): statement is TSESTree.VariableDeclaration => { +export const isVariableDeclaration = (statement: TSESTree.Node): statement is TSESTree.VariableDeclaration => { return statement.type === AST_NODE_TYPES.VariableDeclaration } -export const isVariableDeclarator = ( - statement: TSESTree.Node -): statement is TSESTree.VariableDeclarator => { +export const isVariableDeclarator = (statement: TSESTree.Node): statement is TSESTree.VariableDeclarator => { return statement.type === AST_NODE_TYPES.VariableDeclarator } -export const isFunctionExpression = ( - statement: TSESTree.Node -): statement is TSESTree.FunctionExpression => { +export const isFunctionExpression = (statement: TSESTree.Node): statement is TSESTree.FunctionExpression => { return statement.type === AST_NODE_TYPES.FunctionExpression }