fix(ivy): add missing exportAs field to ngDirectiveDef (#25392)

This commit includes the missing exportAs field from @Directive and
propagates it into the ngDirectiveDef.

PR Close #25392
This commit is contained in:
Alex Rickabaugh 2018-08-06 09:56:43 +02:00 committed by Ben Lesh
parent 5be186035f
commit 6f085f8610
5 changed files with 42 additions and 1 deletions

View File

@ -131,6 +131,16 @@ export function extractDirectiveMetadata(
member => !member.isStatic && member.kind === ClassMemberKind.Method &&
member.name === 'ngOnChanges');
// Parse exportAs.
let exportAs: string|null = null;
if (directive.has('exportAs')) {
const resolved = staticallyResolve(directive.get('exportAs') !, reflector, checker);
if (typeof resolved !== 'string') {
throw new Error(`exportAs must be a string`);
}
exportAs = resolved;
}
// Detect if the component inherits from another class
const usesInheritance = clazz.heritageClauses !== undefined &&
clazz.heritageClauses.some(hc => hc.token === ts.SyntaxKind.ExtendsKeyword);
@ -144,7 +154,7 @@ export function extractDirectiveMetadata(
outputs: {...outputsFromMeta, ...outputsFromFields}, queries, selector,
type: new WrappedNodeExpr(clazz.name !),
typeArgumentCount: (clazz.typeParameters || []).length,
typeSourceSpan: null !, usesInheritance,
typeSourceSpan: null !, usesInheritance, exportAs,
};
return {decoratedElements, decorator: directive, metadata};
}

View File

@ -604,6 +604,26 @@ describe('ngtsc behavioral tests', () => {
expect(jsContents).not.toMatch(/import \* as i[0-9] from ['"].\/test['"]/);
});
it('should generate exportAs declarations', () => {
writeConfig();
write('test.ts', `
import {Component, Directive} from '@angular/core';
@Directive({
selector: '[test]',
exportAs: 'foo',
})
class Dir {}
`);
const exitCode = main(['-p', basePath], errorSpy);
expect(errorSpy).not.toHaveBeenCalled();
expect(exitCode).toBe(0);
const jsContents = getContents('test.js');
expect(jsContents).toContain(`exportAs: "foo"`);
});
it('should generate correct factory stubs for a test module', () => {
writeConfig({'allowEmptyCodegenFiles': true});

View File

@ -96,6 +96,12 @@ export interface R3DirectiveMetadata {
* Whether or not the component or directive inherits from another class
*/
usesInheritance: boolean;
/**
* Reference name under which to export the directive's type in a template,
* if any.
*/
exportAs: string|null;
}
/**

View File

@ -79,6 +79,9 @@ function baseDirectiveFields(
if (features.length) {
definitionMap.set('features', o.literalArr(features));
}
if (meta.exportAs !== null) {
definitionMap.set('exportAs', o.literal(meta.exportAs));
}
return {definitionMap, statements: result.statements};
}
@ -279,6 +282,7 @@ function directiveMetadataFromGlobalMetadata(
inputs: directive.inputs,
outputs: directive.outputs,
usesInheritance: false,
exportAs: null,
};
}

View File

@ -168,6 +168,7 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
},
typeSourceSpan: null !,
usesInheritance: !extendsDirectlyFromObject(type),
exportAs: metadata.exportAs || null,
};
}