Skip to content

Commit

Permalink
feat(transformation): add shift-import transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
tusharmath committed Jul 14, 2018
1 parent 4223beb commit c9cefc0
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 1 deletion.
1 change: 0 additions & 1 deletion src/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export const transform = <T>(
)
debug(`PARAMS:`, transformationParams)
const visitor: ts.Visitor = (node: ts.Node) => {
debug(`NODE: ${node.kind}`)
const visitResult = transformer.visit(node)
return visitResult ? forEachNode(visitor, visitResult, context) : node
}
Expand Down
62 changes: 62 additions & 0 deletions test/shift-imports.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as assert from 'assert'
import ShiftImports from '../transformations/shift-imports'
import {transform, normalize} from '..'

describe('shift-imports', () => {
it('should migrate imports from one module to another', () => {
const input = `
import {a, aa, x, xx} from "a";
import {b, bb, bbb, bbbb, bbbbb} from "b";
`
const expected = normalize(`
import {a, aa} from "a";
import {x, xx} from 'x';
import {b, bb, bbb, bbbb, bbbbb} from "b";
`)

const actual = transform(
ShiftImports,
{content: input, path: './src/file.ts'},
{from: 'a', to: 'x', imports: ['x', 'xx']}
)

assert.strictEqual(actual, expected)
})

it('should skip original module if all imports are shifted', () => {
const input = `
import {x, xx} from "a";
import {b, bb, bbb, bbbb, bbbbb} from "b";
`
const expected = normalize(`
import {x, xx} from 'x';
import {b, bb, bbb, bbbb, bbbbb} from "b";
`)

const actual = transform(
ShiftImports,
{content: input, path: './src/file.ts'},
{from: 'a', to: 'x', imports: ['x', 'xx']}
)

assert.strictEqual(actual, expected)
})
it('should skip the new module if none of the imports are shifted', () => {
const input = `
import {a, aa} from "a";
import {b, bb, bbb, bbbb, bbbbb} from "b";
`
const expected = normalize(`
import {a, aa} from "a";
import {b, bb, bbb, bbbb, bbbbb} from "b";
`)

const actual = transform(
ShiftImports,
{content: input, path: './src/file.ts'},
{from: 'a', to: 'x', imports: ['x', 'xx']}
)

assert.strictEqual(actual, expected)
})
})
87 changes: 87 additions & 0 deletions transformations/shift-imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {Transformation} from '..'
import * as ts from 'typescript'
const debug = require('debug')('ts-codemod:shift-imports')

export default class extends Transformation<{
from: string
to: string
imports: string[]
}> {
visit(node: ts.Node): ts.VisitResult<ts.Node> {
if (
/**
* Check if its an import dec
*/

ts.isImportDeclaration(node) &&
/**
* check if import is for the module in test
*/

ts.isStringLiteral(node.moduleSpecifier) &&
node.moduleSpecifier.text === this.params.from &&
(debug(`MODULE: ${node.moduleSpecifier.text}`) || 1) &&
node.importClause &&
(debug(`HAS: node.importClause`) || 1) &&
node.importClause.namedBindings &&
/**
* Check if import is of type — import {a, b, c} from 'abc';
*/
ts.isNamedImports(node.importClause.namedBindings)
) {
debug(`CREATE IMPORT`)
/**
* Get the import literals — a, b, c part from above
*/
const importLiterals = node.importClause.namedBindings.elements.map(_ =>
_.name.getText()
)

debug(`ORIGINAL: ${importLiterals}`)

/**
* Get original specifiers
*/
const keep = importLiterals.filter(
_ => this.params.imports.indexOf(_) === -1
)
debug(`KEEP: ${keep}`)

/**
* Get original specifiers
*/
const remove = importLiterals.filter(
_ => this.params.imports.indexOf(_) > -1
)
debug(`REMOVE: ${remove}`)

return [
this._createImportDeclaration(this.params.from, keep),
this._createImportDeclaration(this.params.to, remove)
]
}
return node
}

/**
* Creates a new import declaration
*/
private _createImportDeclaration(module: string, keep: string[]): ts.Node {
const importClause = ts.createImportClause(
undefined,
ts.createNamedImports(
keep.map(_ =>
ts.createImportSpecifier(undefined, ts.createIdentifier(_))
)
)
)
return keep.length > 0
? ts.createImportDeclaration(
[],
[],
importClause,
ts.createLiteral(module)
)
: ts.createIdentifier('')
}
}

0 comments on commit c9cefc0

Please sign in to comment.