Skip to content

Commit

Permalink
Merge pull request #35 from line/fix/async-functions
Browse files Browse the repository at this point in the history
fix: don't strip async keyword from function declaration
  • Loading branch information
kazushisan authored Sep 23, 2024
2 parents 876b8fa + 1fce63c commit b23b4ae
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 43 deletions.
1 change: 0 additions & 1 deletion lib/util/applyTextChanges.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ describe('applyTextChanges', () => {
],
);

console.log({ result });
assert.equal(result.startsWith('export const'), true);
});
});
117 changes: 76 additions & 41 deletions lib/util/removeUnusedExport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,64 @@ import c from './c';`,
assert.equal(fileService.get('/app/c.ts'), '');
});

it('should not remove async keyword of function if its not used in some other file', () => {
const { languageService, fileService } = setup();
fileService.set('/app/main.ts', `import { a2 } from './a';`);
fileService.set(
'/app/a.ts',
`export async function a() {}
export function a2() {
a();
}`,
);

removeUnusedExport({
languageService,
fileService,
targetFile: '/app/a.ts',
});

assert.equal(
fileService.get('/app/a.ts'),
`async function a() {}
export function a2() {
a();
}`,
);
});

it('should remove default async function if its not used in some other file', () => {
const { fileService, languageService } = setup();
fileService.set(
'/app/main.ts',
`import { a } from './a';
import { b } from './b';`,
);
fileService.set(
'/app/a.ts',
`export const a = 'a';
export default async function a2() {}`,
);
fileService.set(
'/app/b.ts',
`export const b = 'b';
export default async function() {}`,
);

removeUnusedExport({
languageService,
fileService,
targetFile: ['/app/a.ts', '/app/b.ts'],
});
// async function will be removed afterwards with codeFix
assert.equal(
fileService.get('/app/a.ts'),
`export const a = 'a';
async function a2() {}`,
);
assert.equal(fileService.get('/app/b.ts'), `export const b = 'b';`);
});

it('should not remove export if it has a comment to ignore', () => {
const { languageService, fileService } = setup();
fileService.set(
Expand Down Expand Up @@ -778,31 +836,6 @@ const b: B = 'b';`,
);
});

it('should remove export keyword of interface declaration if its not used in any other file', () => {
const { languageService, fileService } = setup();
fileService.set('/app/main.ts', `import { a } from './a';`);

fileService.set(
'/app/a.ts',
`export const a = 'a';
export interface B {}
const b: B = {};`,
);

removeUnusedExport({
languageService,
fileService,
targetFile: '/app/a.ts',
});

assert.equal(
fileService.get('/app/a.ts'),
`export const a = 'a';
interface B {}
const b: B = {};`,
);
});

describe('dynamic import', () => {
it('should not remove export if its used in dynamic import', () => {
const { languageService, fileService } = setup();
Expand Down Expand Up @@ -1002,26 +1035,28 @@ import('./b.js');`,
});

describe('enableCodeFix', () => {
const { languageService, fileService } = setup();
it('should apply code fix when enableCodeFix is true', () => {
const { languageService, fileService } = setup();

fileService.set('/app/main.ts', `import { remain } from './a';`);
fileService.set(
'/app/a.ts',
`const dep = 'dep';
fileService.set('/app/main.ts', `import { remain } from './a';`);
fileService.set(
'/app/a.ts',
`const dep = 'dep';
export const a = () => dep;
export const remain = 'remain';`,
);
);

removeUnusedExport({
languageService,
fileService,
targetFile: '/app/a.ts',
enableCodeFix: true,
});
removeUnusedExport({
languageService,
fileService,
targetFile: '/app/a.ts',
enableCodeFix: true,
});

assert.equal(
fileService.get('/app/a.ts'),
`export const remain = 'remain';`,
);
assert.equal(
fileService.get('/app/a.ts'),
`export const remain = 'remain';`,
);
});
});
});
42 changes: 41 additions & 1 deletion lib/util/removeUnusedExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,44 @@ const getUpdatedExportDeclaration = (
return result ? printer.printFile(result).trim() : '';
};

const stripExportKeyword = (syntaxList: ts.Node) => {
const file = ts.createSourceFile(
'tmp.ts',
`${syntaxList.getText()} function f() {}`,
syntaxList.getSourceFile().languageVersion,
);

const transformer: ts.TransformerFactory<ts.SourceFile> =
(context: ts.TransformationContext) => (rootNode: ts.SourceFile) => {
const visitor = (node: ts.Node): ts.Node | undefined => {
if (ts.isFunctionDeclaration(node)) {
return ts.factory.createFunctionDeclaration(
node.modifiers?.filter(
(v) =>
v.kind !== ts.SyntaxKind.ExportKeyword &&
v.kind !== ts.SyntaxKind.DefaultKeyword,
),
node.asteriskToken,
node.name,
node.typeParameters,
node.parameters,
node.type,
node.body,
);
}
return ts.visitEachChild(node, visitor, context);
};

return ts.visitEachChild(rootNode, visitor, context);
};

const result = ts.transform(file, [transformer]).transformed[0];
const printer = ts.createPrinter();
const code = result ? printer.printFile(result).trim() : '';
const pos = code.indexOf('function');
return code.slice(0, pos);
};

const getTextChanges = (
languageService: ts.LanguageService,
file: string,
Expand Down Expand Up @@ -483,7 +521,9 @@ const getTextChanges = (
}

changes.push({
newText: '',
newText: ts.isFunctionDeclaration(node)
? stripExportKeyword(syntaxList)
: '',
span: {
start: syntaxList.getStart(),
length: syntaxListNextSibling.getStart() - syntaxList.getStart(),
Expand Down

0 comments on commit b23b4ae

Please sign in to comment.