From a75e2fbcfee940b69c905bc7414315e97942cd15 Mon Sep 17 00:00:00 2001 From: Tushar Mathur Date: Thu, 2 Aug 2018 13:01:13 +0530 Subject: [PATCH] fix(replace-node): compare children only when the node.kind is not of type Identifier --- src/eq-node.ts | 29 ++++++++++++++++++++++------- test/replace-node.test.ts | 19 +++++++++++++++++++ transformations/replace-node.ts | 22 +++++++++++++++++++--- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/eq-node.ts b/src/eq-node.ts index 3c4bbb4..b96f7be 100644 --- a/src/eq-node.ts +++ b/src/eq-node.ts @@ -1,21 +1,36 @@ import * as ts from 'typescript' - +const debug = require('debug')('ts-codemod:eq') export function eqNode(a: ts.Node, b: ts.Node): boolean { - return ( - strictlyEq(a, b) || eqIdentifier(a, b) || (eqKind(a, b) && eqChildren(a, b)) - ) + return strictlyEq(a, b) || eqIdentifier(a, b) || eqChildren(a, b) } function eqChildren(a: ts.Node, b: ts.Node): boolean { - return a.getChildren().every((aChild, id) => eqNode(b.getChildAt(id), aChild)) + /** + * Children comparison should happen only for nodes that are + * not of type Identifier + */ + if (eqKind(a, b) && !ts.isIdentifier(a)) { + const result = a + .getChildren() + .every((aChild, id) => eqNode(b.getChildAt(id), aChild)) + if (result) + debug('children:', `'${a.getFullText()}'`, `'${b.getFullText()}'`) + return result + } + return false } function eqKind(a: ts.Node, b: ts.Node) { - return a.kind === b.kind + const result = a.kind === b.kind + if (result) debug('kind:', `'${a.getFullText()}'`, `'${b.getFullText()}'`) + if (result) return result } function eqIdentifier(a: ts.Node, b: ts.Node): boolean { - return ts.isIdentifier(a) && ts.isIdentifier(b) && a.text === b.text + const result = ts.isIdentifier(a) && ts.isIdentifier(b) && a.text === b.text + if (result) + debug('identifier:', `'${a.getFullText()}'`, `'${b.getFullText()}'`) + return result } function strictlyEq(a: ts.Node, b: ts.Node) { diff --git a/test/replace-node.test.ts b/test/replace-node.test.ts index 16c4a6c..b6936c8 100644 --- a/test/replace-node.test.ts +++ b/test/replace-node.test.ts @@ -23,4 +23,23 @@ describe('replace-node', () => { }).newContent assert.strictEqual(actual, expected) }) + + it('should convert identifiers', () => { + const input = normalize(` + import {Hoe} from '@action-land/core' + export const view = (e: Hoe, m: {}, p: {}) => 'Hello' + `) + const expected = normalize(` + import {Smitten} from '@action-land/core' + export const view = (e: Smitten, m: {}, p: {}) => 'Hello' + `) + + const actual = transform({ + transformationCtor: ReplaceNode, + content: input, + path: './src/file.ts', + params: {matchWith: 'Hoe', replaceWith: 'Smitten'} + }).newContent + assert.strictEqual(actual, expected) + }) }) diff --git a/transformations/replace-node.ts b/transformations/replace-node.ts index ef719a1..4c9c921 100644 --- a/transformations/replace-node.ts +++ b/transformations/replace-node.ts @@ -1,5 +1,8 @@ import {Transformation} from '..' import * as ts from 'typescript' +const debug = require('debug')('ts-codemod:replace-node') + +const cName = (obj: any) => obj.constructor.name.replace('Object', '') export default class ReplaceNode extends Transformation<{ matchWith: string @@ -9,11 +12,24 @@ export default class ReplaceNode extends Transformation<{ private replaceWith: ts.Node = ts.createEmptyStatement() init() { - this.matchWith = this.toNode(this.params.matchWith) - this.replaceWith = this.toNode(this.params.replaceWith) + const {matchWith, replaceWith} = this.params + this.matchWith = this.toNode(matchWith) + this.replaceWith = this.toNode(replaceWith) + debug('matchWith:', cName(this.matchWith), `'${matchWith}'`) + debug('replaceWith:', cName(this.replaceWith), `'${replaceWith}'`) } visit(node: ts.Node): ts.VisitResult { - return this.equal(node, this.matchWith) ? this.replaceWith : node + debug('node:', cName(node), `'${node.getFullText()}'`) + if (this.equal(node, this.matchWith)) { + debug( + 'replacing', + node.getFullText(), + 'with', + this.replaceWith.getFullText() + ) + return this.replaceWith + } + return node } }