in src/cdk/schematics/update-tool/component-resource-collector.ts [56:171]
private _visitClassDeclaration(node: ts.ClassDeclaration) {
if (!node.decorators || !node.decorators.length) {
return;
}
const ngDecorators = getAngularDecorators(this.typeChecker, node.decorators);
const componentDecorator = ngDecorators.find(dec => dec.name === 'Component');
// In case no "@Component" decorator could be found on the current class, skip.
if (!componentDecorator) {
return;
}
const decoratorCall = componentDecorator.node.expression;
// In case the component decorator call is not valid, skip this class declaration.
if (decoratorCall.arguments.length !== 1) {
return;
}
const componentMetadata = unwrapExpression(decoratorCall.arguments[0]);
// Ensure that the component metadata is an object literal expression.
if (!ts.isObjectLiteralExpression(componentMetadata)) {
return;
}
const sourceFile = node.getSourceFile();
const filePath = this._fileSystem.resolve(sourceFile.fileName);
const sourceFileDirPath = dirname(sourceFile.fileName);
// Walk through all component metadata properties and determine the referenced
// HTML templates (either external or inline)
componentMetadata.properties.forEach(property => {
if (!ts.isPropertyAssignment(property)) {
return;
}
const propertyName = getPropertyNameText(property.name);
if (propertyName === 'styles' && ts.isArrayLiteralExpression(property.initializer)) {
property.initializer.elements.forEach(el => {
if (ts.isStringLiteralLike(el)) {
// Need to add an offset of one to the start because the template quotes are
// not part of the template content.
const templateStartIdx = el.getStart() + 1;
this.resolvedStylesheets.push({
filePath,
container: node,
content: el.text,
inline: true,
start: templateStartIdx,
getCharacterAndLineOfPosition: pos =>
ts.getLineAndCharacterOfPosition(sourceFile, pos + templateStartIdx),
});
}
});
}
// In case there is an inline template specified, ensure that the value is statically
// analyzable by checking if the initializer is a string literal-like node.
if (propertyName === 'template' && ts.isStringLiteralLike(property.initializer)) {
// Need to add an offset of one to the start because the template quotes are
// not part of the template content.
const templateStartIdx = property.initializer.getStart() + 1;
this.resolvedTemplates.push({
filePath,
container: node,
content: property.initializer.text,
inline: true,
start: templateStartIdx,
getCharacterAndLineOfPosition: pos =>
ts.getLineAndCharacterOfPosition(sourceFile, pos + templateStartIdx),
});
}
if (propertyName === 'styleUrls' && ts.isArrayLiteralExpression(property.initializer)) {
property.initializer.elements.forEach(el => {
if (ts.isStringLiteralLike(el)) {
const stylesheetPath = this._fileSystem.resolve(sourceFileDirPath, el.text);
const stylesheet = this.resolveExternalStylesheet(stylesheetPath, node);
if (stylesheet) {
this.resolvedStylesheets.push(stylesheet);
}
}
});
}
if (propertyName === 'templateUrl' && ts.isStringLiteralLike(property.initializer)) {
const templateUrl = property.initializer.text;
const templatePath = this._fileSystem.resolve(sourceFileDirPath, templateUrl);
// In case the template does not exist in the file system, skip this
// external template.
if (!this._fileSystem.fileExists(templatePath)) {
return;
}
const fileContent = this._fileSystem.read(templatePath);
if (fileContent) {
const lineStartsMap = computeLineStartsMap(fileContent);
this.resolvedTemplates.push({
filePath: templatePath,
container: node,
content: fileContent,
inline: false,
start: 0,
getCharacterAndLineOfPosition: p => getLineAndCharacterFromPosition(lineStartsMap, p),
});
}
}
});
}