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 angular#24295
  • Loading branch information
alan-agius4 committed Nov 24, 2022
1 parent 534921c commit 4a54d1c
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 4a54d1c

Please sign in to comment.