forked from tusharmath/ts-codemod
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(transformation): add shift-import transformation
- Loading branch information
1 parent
4223beb
commit c9cefc0
Showing
3 changed files
with
149 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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('') | ||
} | ||
} |