Fix potential bug when extracting strings from file containing multiple classes
This commit is contained in:
		| @@ -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] : []; | ||||
|  | ||||
|   | ||||
| @@ -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]; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -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!']); | ||||
| 	}); | ||||
|  | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user