Skip to content

Commit

Permalink
Merge pull request #108 from FredericEspiau/fix/decorator-removal
Browse files Browse the repository at this point in the history
fix: prevent removing decorators on classes
  • Loading branch information
kazushisan authored Dec 17, 2024
2 parents 50b9261 + c1303ce commit 6ed047a
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
47 changes: 47 additions & 0 deletions lib/util/edit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,53 @@ function a2() {}`,
});

describe('class declaration', () => {
it('should not remove decorators when exports are deleted', () => {
const fileService = new MemoryFileService();

fileService.set('/app/main.ts', ``);
fileService.set(
'/app/a.ts',
`@myDecorator
export class A {}`,
);
fileService.set(
'/app/b.ts',
`@myDecorator
export default class B {}`,
);
fileService.set(
'/app/c.ts',
`@firstDecorator
@secondDecorator(() => [WithArgument])
export default class C {}`,
);

edit({
fileService,
recursive,
entrypoints: ['/app/main.ts'],
});

assert.equal(
fileService.get('/app/a.ts'),
`@myDecorator
class A {}`,
);

assert.equal(
fileService.get('/app/b.ts'),
`@myDecorator
class B {}`,
);

assert.equal(
fileService.get('/app/c.ts'),
`@firstDecorator
@secondDecorator(() => [WithArgument])
class C {}`,
);
});

it('should not remove export for class if its used in some other file', () => {
const fileService = new MemoryFileService();

Expand Down
34 changes: 27 additions & 7 deletions lib/util/parseFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,47 @@ const getChange = (
};
}

// we want to correctly remove 'default' when its a default export so we get the syntaxList node instead of the exportKeyword node
// note: the first syntaxList node should contain the export keyword
/**
* The syntax list contains the keywords that can be found before the actual declaration.
* We want to remove everything that is not a decorator.
*/
const syntaxListIndex = node
.getChildren()
.findIndex((n) => n.kind === ts.SyntaxKind.SyntaxList);

const syntaxList = node.getChildren()[syntaxListIndex];

if (!syntaxList) {
throw new Error('syntaxList missing');
}

const firstKeywordToDeleteIndex = syntaxList
.getChildren()
.findIndex((n) => n.kind !== ts.SyntaxKind.Decorator);

const firstKeywordToDelete =
syntaxList.getChildren()[firstKeywordToDeleteIndex];

if (!firstKeywordToDelete) {
throw new Error(
'Unexpected syntax list when looking for keywords after decorators',
);
}

const nextSibling = node.getChildren()[syntaxListIndex + 1];

if (!syntaxList || !nextSibling) {
throw new Error('Unexpected syntax');
if (!nextSibling) {
throw new Error('No sibling after syntax list');
}

return {
code: node
.getSourceFile()
.getFullText()
.slice(syntaxList.getStart(), nextSibling.getStart()),
.slice(firstKeywordToDelete.getStart(), nextSibling.getStart()),
span: {
start: syntaxList.getStart(),
length: nextSibling.getStart() - syntaxList.getStart(),
start: firstKeywordToDelete.getStart(),
length: nextSibling.getStart() - firstKeywordToDelete.getStart(),
},
};
};
Expand Down

0 comments on commit 6ed047a

Please sign in to comment.