Fix potential bug when extracting strings from file containing multiple classes

This commit is contained in:
Kim Biesbjerg 2017-05-10 14:10:13 +02:00
parent a6c7af0630
commit 4ee7258a31
3 changed files with 40 additions and 20 deletions

View File

@ -35,11 +35,7 @@ export abstract class AbstractAstParser {
/**
* Find all child nodes of a kind
*/
protected _findNodes(node: ts.Node, kind: ts.SyntaxKind, onlyOne: boolean = false): ts.Node[] {
if (node.kind === kind && onlyOne) {
return [node];
}
protected _findNodes(node: ts.Node, kind: ts.SyntaxKind): ts.Node[] {
const childrenNodes: ts.Node[] = node.getChildren(this._sourceFile);
const initialValue: ts.Node[] = node.kind === kind ? [node] : [];

View File

@ -9,18 +9,22 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface
protected _sourceFile: ts.SourceFile;
public extract(contents: string, path?: string): TranslationCollection {
this._sourceFile = this._createSourceFile(path, contents);
let collection: TranslationCollection = new TranslationCollection();
const constructorNodes: ts.ConstructorDeclaration[] = this._findConstructorNodes();
constructorNodes.forEach(constructorNode => {
const propertyName: string = this._getPropertyName(constructorNode);
this._sourceFile = this._createSourceFile(path, contents);
const classNodes = this._findClassNodes(this._sourceFile);
classNodes.forEach(classNode => {
const constructorNode = this._findConstructorNode(classNode);
if (!constructorNode) {
return;
}
const propertyName: string = this._findTranslateServicePropertyName(constructorNode);
if (!propertyName) {
return;
}
const callNodes = this._findCallNodes(this._sourceFile, propertyName);
const callNodes = this._findCallNodes(classNode, propertyName);
callNodes.forEach(callNode => {
const keys: string[] = this._getCallArgStrings(callNode);
if (keys && keys.length) {
@ -34,9 +38,9 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface
/**
* Detect what the TranslateService instance property
* is called by inspecting constructor params
* is called by inspecting constructor arguments
*/
protected _getPropertyName(constructorNode: ts.ConstructorDeclaration): string {
protected _findTranslateServicePropertyName(constructorNode: ts.ConstructorDeclaration): string {
if (!constructorNode) {
return null;
}
@ -71,12 +75,19 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface
}
/**
* Find constructor nodes
* Find class nodes
*/
protected _findConstructorNodes(): ts.ConstructorDeclaration[] {
const constructors = this._findNodes(this._sourceFile, ts.SyntaxKind.Constructor, true) as ts.ConstructorDeclaration[];
if (constructors.length) {
return constructors;
protected _findClassNodes(node: ts.Node): ts.ClassDeclaration[] {
return this._findNodes(node, ts.SyntaxKind.ClassDeclaration) as ts.ClassDeclaration[];
}
/**
* Find constructor
*/
protected _findConstructorNode(node: ts.ClassDeclaration): ts.ConstructorDeclaration {
const constructorNodes = this._findNodes(node, ts.SyntaxKind.Constructor) as ts.ConstructorDeclaration[];
if (constructorNodes) {
return constructorNodes[0];
}
}

View File

@ -170,19 +170,32 @@ describe('ServiceParser', () => {
import { TranslateService } from '@ngx-translate/core';
export class Stuff {
thing: string;
translate: any;
constructor(thing: string) {
this.translate.get('Not me');
this.thing = thing;
}
}
@Injectable()
export class MyComponent {
constructor(public translate: TranslateService) {
this.translate.instant("Extract me!");
}
}
export class OtherClass {
constructor(thing: string, _translate: TranslateService) {
this._translate.get("Do not extract me");
}
}
@Injectable()
export class AuthService {
constructor(public translate: TranslateService) {
console.log(this.translate.instant("Hello!"));
this.translate.instant("Hello!");
}
}
`;
const keys = parser.extract(contents, componentFilename).keys();
expect(keys).to.deep.equal(['Hello!']);
expect(keys).to.deep.equal(['Extract me!', 'Hello!']);
});
});