Skip to content

Commit

Permalink
fix(@ngtools/webpack): elide unused type references
Browse files Browse the repository at this point in the history
In the case the import declaration has an unused import we did not properly elide type references when `emitDecoratorMetadata` is disabled.

Closes #24295

(cherry picked from commit 856720b)
  • Loading branch information
alan-agius4 committed Nov 28, 2022
1 parent 2891d5b commit d9cc4b0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 23 deletions.
49 changes: 26 additions & 23 deletions packages/ngtools/webpack/src/transformers/elide_imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,31 +54,34 @@ export function elideImports(
return;
}

if (!ts.isTypeReferenceNode(node)) {
let symbol: ts.Symbol | undefined;
switch (node.kind) {
case ts.SyntaxKind.Identifier:
const parent = node.parent;
if (parent && ts.isShorthandPropertyAssignment(parent)) {
const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(parent);
if (shorthandSymbol) {
symbol = shorthandSymbol;
}
} else {
symbol = typeChecker.getSymbolAtLocation(node);
// Type reference imports do not need to be emitted when emitDecoratorMetadata is disabled.
if (ts.isTypeReferenceNode(node) && !compilerOptions.emitDecoratorMetadata) {
return;
}

let symbol: ts.Symbol | undefined;
switch (node.kind) {
case ts.SyntaxKind.Identifier:
const parent = node.parent;
if (parent && ts.isShorthandPropertyAssignment(parent)) {
const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(parent);
if (shorthandSymbol) {
symbol = shorthandSymbol;
}
break;
case ts.SyntaxKind.ExportSpecifier:
symbol = typeChecker.getExportSpecifierLocalTargetSymbol(node as ts.ExportSpecifier);
break;
case ts.SyntaxKind.ShorthandPropertyAssignment:
symbol = typeChecker.getShorthandAssignmentValueSymbol(node);
break;
}
} else {
symbol = typeChecker.getSymbolAtLocation(node);
}
break;
case ts.SyntaxKind.ExportSpecifier:
symbol = typeChecker.getExportSpecifierLocalTargetSymbol(node as ts.ExportSpecifier);
break;
case ts.SyntaxKind.ShorthandPropertyAssignment:
symbol = typeChecker.getShorthandAssignmentValueSymbol(node);
break;
}

if (symbol) {
usedSymbols.add(symbol);
}
if (symbol) {
usedSymbols.add(symbol);
}

ts.forEachChild(node, visit);
Expand Down
40 changes: 40 additions & 0 deletions packages/ngtools/webpack/src/transformers/elide_imports_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ describe('@ngtools/webpack transformers', () => {
`,
'service.ts': `
export class Service { }
export class Service2 { }
`,
'type.ts': `
export interface OnChanges {
Expand Down Expand Up @@ -385,6 +386,45 @@ describe('@ngtools/webpack transformers', () => {

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should remove ctor parameter type reference and unused named import from same declaration', () => {
const input = tags.stripIndent`
import { Decorator } from './decorator';
import { Service, Service2 as ServiceUnused } from './service';
@Decorator()
export class Foo {
constructor(param: Service) {
}
}
${dummyNode}
`;

const output = tags.stripIndent`
import { __decorate } from "tslib";
import { Decorator } from './decorator';
let Foo = class Foo { constructor(param) { } };
Foo = __decorate([ Decorator() ], Foo);
export { Foo };
`;

const { program, compilerHost } = createTypescriptContext(
input,
additionalFiles,
true,
extraCompilerOptions,
);
const result = transformTypescript(
undefined,
[transformer(program)],
program,
compilerHost,
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});
});

it('keeps jsxFactory imports when configured', () => {
Expand Down

0 comments on commit d9cc4b0

Please sign in to comment.