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 * Find all child nodes of a kind
*/ */
protected _findNodes(node: ts.Node, kind: ts.SyntaxKind, onlyOne: boolean = false): ts.Node[] { protected _findNodes(node: ts.Node, kind: ts.SyntaxKind): ts.Node[] {
if (node.kind === kind && onlyOne) {
return [node];
}
const childrenNodes: ts.Node[] = node.getChildren(this._sourceFile); const childrenNodes: ts.Node[] = node.getChildren(this._sourceFile);
const initialValue: ts.Node[] = node.kind === kind ? [node] : []; 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; protected _sourceFile: ts.SourceFile;
public extract(contents: string, path?: string): TranslationCollection { public extract(contents: string, path?: string): TranslationCollection {
this._sourceFile = this._createSourceFile(path, contents);
let collection: TranslationCollection = new TranslationCollection(); let collection: TranslationCollection = new TranslationCollection();
const constructorNodes: ts.ConstructorDeclaration[] = this._findConstructorNodes(); this._sourceFile = this._createSourceFile(path, contents);
constructorNodes.forEach(constructorNode => { const classNodes = this._findClassNodes(this._sourceFile);
const propertyName: string = this._getPropertyName(constructorNode); classNodes.forEach(classNode => {
const constructorNode = this._findConstructorNode(classNode);
if (!constructorNode) {
return;
}
const propertyName: string = this._findTranslateServicePropertyName(constructorNode);
if (!propertyName) { if (!propertyName) {
return; return;
} }
const callNodes = this._findCallNodes(this._sourceFile, propertyName); const callNodes = this._findCallNodes(classNode, propertyName);
callNodes.forEach(callNode => { callNodes.forEach(callNode => {
const keys: string[] = this._getCallArgStrings(callNode); const keys: string[] = this._getCallArgStrings(callNode);
if (keys && keys.length) { if (keys && keys.length) {
@ -34,9 +38,9 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface
/** /**
* Detect what the TranslateService instance property * 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) { if (!constructorNode) {
return null; return null;
} }
@ -71,12 +75,19 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface
} }
/** /**
* Find constructor nodes * Find class nodes
*/ */
protected _findConstructorNodes(): ts.ConstructorDeclaration[] { protected _findClassNodes(node: ts.Node): ts.ClassDeclaration[] {
const constructors = this._findNodes(this._sourceFile, ts.SyntaxKind.Constructor, true) as ts.ConstructorDeclaration[]; return this._findNodes(node, ts.SyntaxKind.ClassDeclaration) as ts.ClassDeclaration[];
if (constructors.length) { }
return constructors;
/**
* 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'; import { TranslateService } from '@ngx-translate/core';
export class Stuff { export class Stuff {
thing: string; thing: string;
translate: any;
constructor(thing: string) { constructor(thing: string) {
this.translate.get('Not me');
this.thing = thing; this.thing = thing;
} }
} }
@Injectable() @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 { export class AuthService {
constructor(public translate: TranslateService) { constructor(public translate: TranslateService) {
console.log(this.translate.instant("Hello!")); this.translate.instant("Hello!");
} }
} }
`; `;
const keys = parser.extract(contents, componentFilename).keys(); const keys = parser.extract(contents, componentFilename).keys();
expect(keys).to.deep.equal(['Hello!']); expect(keys).to.deep.equal(['Extract me!', 'Hello!']);
}); });
}); });