diff --git a/src/rules/strict-mutable.ts b/src/rules/strict-mutable.ts index 1a31770..b32febd 100644 --- a/src/rules/strict-mutable.ts +++ b/src/rules/strict-mutable.ts @@ -42,66 +42,10 @@ const rule: Rule.RuleModule = { const mutable = parsed && parsed.length && parsed[0].mutable || false; if (mutable) { const varName = node.parent.key.name; - mutableProps.set(varName, node.parent); + mutableProps.set(varName, node); } } - // function getName(expression: any) { - // if (expression.left && expression.left.name) { - // return expression.left.name; - // } - // return null; - // } - // - // function parseExpression(expression: any): any { - // if (!expression) { - // return null; - // } - // if (expression.expression) { - // return parseExpression(expression.expression); - // } - // if (expression.openingElement) { - // const container = expression.openingElement.attributes && expression.openingElement.attributes.nextContainer; - // if (container) { - // return container.body && container.body.expression ? removeUsedVars(container.body) : parseExpression(container.body); - // } else { - // return null; - // } - // } - // return expression && getName(expression); - // } - // - // function removeUsedVars(statements: any[]) { - // statements - // .map((st) => st.expression && parseExpression(st.expression)) - // .filter((name) => !!name) - // .forEach((name) => { - // mutableProps.delete(name.escapedText); - // }); - // statements - // .filter((st) => st.thenStatement && st.thenStatement.statements) - // .map((st) => st.thenStatement.statements) - // .forEach((st) => { - // removeUsedVars(st); - // }); - // statements - // .filter((st) => st.elseStatement) - // .forEach((st) => { - // const sts = Array.isArray(st.elseStatement) ? st.elseStatement : [st.elseStatement]; - // removeUsedVars(sts); - // }); - // } - - // function getJsonPath(element: any, path: string[]) { - // const name = path[0]; - // const value = element[name]; - // if (path.length === 1) { - // return value; - // } else { - // return value && getJsonPath(value, path.slice(1)); - // } - // } - function removeVar(name: any) { if (!name) { return; @@ -123,27 +67,24 @@ const rule: Rule.RuleModule = { return; } const { expression, thenStatement, elseStatement } = st; - console.log('kind:', !!expression, st.getText()); [...getArray(thenStatement), ...getArray(elseStatement), expression].filter((ex) => !!ex).forEach(checkExpression); - console.log('statement end'); } function checkExpression(expr: any) { if (!expr) { return; } - const { expression, left, openingElement, nextContainer, body, statements, thenStatement } = expr; + const { expression, left, openingElement, body, nextContainer, statements, thenStatement } = expr; if (left && left.name && expr.operatorToken && ASSIGN_TOKENS.includes(expr.operatorToken.kind)) { removeVar(left.name); } if (openingElement) { getArray(openingElement.attributes).forEach(checkExpression); } - [...getArray(thenStatement), expression, nextContainer, body].filter((ex) => !!ex).forEach(checkExpression); + [...getArray(thenStatement), expression, body, nextContainer].filter((ex) => !!ex).forEach(checkExpression); if (statements) { statements.forEach(checkStatement); } - console.log('expression'); } return { @@ -167,26 +108,26 @@ const rule: Rule.RuleModule = { } stencil.rules['ClassDeclaration:exit'](node); mutableProps.forEach((varNode, varName) => { - const originalNode = parserServices.esTreeNodeToTSNodeMap.get(varNode); + const originalNode = parserServices.esTreeNodeToTSNodeMap.get(varNode.parent); const text = originalNode.getFullText(); const parsed = parseDecorator(varNode); context.report({ - node: varNode, + node: varNode.parent, message: `@Prop() "${varName}" should not be mutable`, fix(fixer) { - // const options = parsed && parsed.length && parsed[0] || {}; - // delete options.mutable; - // let opts = ''; - // if (options && Object.keys(options).length) { - // opts = Object.keys(options).map((key) => { - // const value = options[key]; - // const val = typeof value === 'string' ? `'${value}'` : value; - // return `${key}: ${val}`; - // }).join(', '); - // opts = `{ ${opts} }`; - // } - // const result = text.replace(/@Prop\((.*)?\)/, `@Prop(${opts})`); - return fixer.replaceText(varNode, text); + const options = parsed && parsed.length && parsed[0] || {}; + delete options.mutable; + let opts = ''; + if (options && Object.keys(options).length) { + opts = Object.keys(options).map((key) => { + const value = options[key]; + const val = typeof value === 'string' ? `'${value}'` : value; + return `${key}: ${val}`; + }).join(', '); + opts = `{ ${opts} }`; + } + const result = text.replace(/@Prop\((.*)?\)/, `@Prop(${opts})`); + return fixer.replaceText(varNode, result); } }); }); diff --git a/src/utils.ts b/src/utils.ts index da6372d..7628f9c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -22,7 +22,7 @@ export function getDecorator(node: any, decoratorName?: string): any | any[] { } export function parseDecorator(decorator: any) { - if (decorator && decorator.expression.type === 'CallExpression') { + if (decorator && decorator.expression && decorator.expression.type === 'CallExpression') { return decorator.expression.arguments.map((a: any) => { const parsed = getStaticValue(a); return parsed ? parsed.value : undefined; diff --git a/tests/lib/rules/strict-mutable/strict-mutable.good.tsx b/tests/lib/rules/strict-mutable/strict-mutable.good.tsx index 70aafaf..8ae98f1 100644 --- a/tests/lib/rules/strict-mutable/strict-mutable.good.tsx +++ b/tests/lib/rules/strict-mutable/strict-mutable.good.tsx @@ -27,13 +27,13 @@ export class SampleTag { render() { return ( -