Skip to content

Commit da2eb05

Browse files
committed
TypescriptAPIUtils: add appendImport function
1 parent 83e8d18 commit da2eb05

20 files changed

+217
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import {clone, exists, find} from '@slicky/utils';
2+
import {findNodesByType} from './findNodesByType';
3+
import * as ts from 'typescript';
4+
5+
6+
export function appendImport(moduleSpecifier: string, propertyName: string|undefined, name: string, sourceFile: ts.SourceFile): string
7+
{
8+
const imports = findNodesByType<ts.ImportDeclaration>(ts.SyntaxKind.ImportDeclaration, sourceFile);
9+
const pos = imports.length ? (sourceFile.statements.indexOf(imports[imports.length - 1]) || 0) : 0;
10+
11+
const existingImport: ts.ImportDeclaration = find(imports, (existingImport: ts.ImportDeclaration) => {
12+
return (
13+
exists(existingImport.importClause) &&
14+
exists(existingImport.importClause.namedBindings) &&
15+
ts.isNamedImports(existingImport.importClause.namedBindings) &&
16+
ts.isStringLiteral(existingImport.moduleSpecifier) &&
17+
(<ts.StringLiteral>existingImport.moduleSpecifier).text === moduleSpecifier
18+
);
19+
});
20+
21+
if (existingImport) {
22+
const namedBindings = <ts.NamedImports>existingImport.importClause.namedBindings;
23+
const elements = clone(namedBindings.elements);
24+
25+
const existingElement: ts.ImportSpecifier = find(elements, (existingElement: ts.ImportSpecifier) => {
26+
return (
27+
(<ts.Identifier>existingElement.name).text === name ||
28+
(
29+
exists(existingElement.propertyName) &&
30+
(<ts.Identifier>existingElement.propertyName).text === name
31+
) ||
32+
(
33+
exists(propertyName) &&
34+
exists(existingElement.propertyName) &&
35+
(<ts.Identifier>existingElement.propertyName).text === propertyName
36+
) ||
37+
(
38+
!exists(existingElement.propertyName) &&
39+
exists(propertyName) &&
40+
(<ts.Identifier>existingElement.name).text === propertyName
41+
)
42+
);
43+
});
44+
45+
if (existingElement) {
46+
if (exists(propertyName) && exists(existingElement.propertyName) && propertyName !== (<ts.Identifier>existingElement.propertyName).text) {
47+
throw new Error(`appendImport: can not append new import {${propertyName} as ${name}}. File already contains import with the same name {${(<ts.Identifier>existingElement.propertyName).text} as ${(<ts.Identifier>existingElement.name).text}}.`);
48+
}
49+
50+
return (<ts.Identifier>existingElement.name).text;
51+
52+
} else {
53+
elements.push(createNewImportSpecifier(propertyName, name));
54+
namedBindings.elements = elements;
55+
}
56+
57+
} else {
58+
const statements = clone(sourceFile.statements);
59+
60+
statements.splice(pos, 0, createNewImportDeclaration(moduleSpecifier, propertyName, name));
61+
sourceFile.statements = statements;
62+
}
63+
64+
return name;
65+
}
66+
67+
68+
function createNewImportDeclaration(moduleSpecifier: string, propertyName: string|undefined, name: string): ts.ImportDeclaration
69+
{
70+
return ts.createImportDeclaration(
71+
[],
72+
[],
73+
ts.createImportClause(
74+
undefined,
75+
ts.createNamedImports([
76+
createNewImportSpecifier(propertyName, name),
77+
]),
78+
),
79+
ts.createLiteral(moduleSpecifier),
80+
);
81+
}
82+
83+
84+
function createNewImportSpecifier(propertyName: string|undefined, name: string): ts.ImportSpecifier
85+
{
86+
return ts.createImportSpecifier(
87+
exists(propertyName) ? ts.createIdentifier(propertyName) : undefined,
88+
ts.createIdentifier(name),
89+
);
90+
}

packages/typescript-api-utils/sourceFiles/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './appendImport';
12
export * from './findNode';
23
export * from './findLastNodeOfType';
34
export * from './findNodesByType';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import {A1 as B} from '/import';

packages/typescript-api-utils/tests/data/sourceFiles/appendImport/valid_1.original.ts

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { A } from "/import";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import {A} from '/import';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { A, B } from "/import";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import {A} from '/import';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import { A } from "/import";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import {A as B} from '/import';

0 commit comments

Comments
 (0)