extract strings when TranslateService is accessed directly via constructor parameter. Closes #50 and #106
This commit is contained in:
parent
b07d929484
commit
33d8c26a28
@ -1,8 +1,9 @@
|
|||||||
|
import { ClassDeclaration, CallExpression } from 'typescript';
|
||||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
|
|
||||||
import { ParserInterface } from './parser.interface';
|
import { ParserInterface } from './parser.interface';
|
||||||
import { TranslationCollection } from '../utils/translation.collection';
|
import { TranslationCollection } from '../utils/translation.collection';
|
||||||
import { findClassDeclarations, findClassPropertyByType, findMethodCallExpressions, getStringsFromExpression } from '../utils/ast-helpers';
|
import { findClassDeclarations, findClassPropertyByType, findPropertyCallExpressions, findMethodCallExpressions, getStringsFromExpression, findMethodParameterByType, findConstructorDeclaration } from '../utils/ast-helpers';
|
||||||
|
|
||||||
const TRANSLATE_SERVICE_TYPE_REFERENCE = 'TranslateService';
|
const TRANSLATE_SERVICE_TYPE_REFERENCE = 'TranslateService';
|
||||||
const TRANSLATE_SERVICE_METHOD_NAMES = ['get', 'instant', 'stream'];
|
const TRANSLATE_SERVICE_METHOD_NAMES = ['get', 'instant', 'stream'];
|
||||||
@ -19,12 +20,11 @@ export class ServiceParser implements ParserInterface {
|
|||||||
let collection: TranslationCollection = new TranslationCollection();
|
let collection: TranslationCollection = new TranslationCollection();
|
||||||
|
|
||||||
classDeclarations.forEach(classDeclaration => {
|
classDeclarations.forEach(classDeclaration => {
|
||||||
const propName: string = findClassPropertyByType(classDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE);
|
const callExpressions = [
|
||||||
if (!propName) {
|
...this.findConstructorParamCallExpressions(classDeclaration),
|
||||||
return;
|
...this.findPropertyCallExpressions(classDeclaration)
|
||||||
}
|
];
|
||||||
|
|
||||||
const callExpressions = findMethodCallExpressions(classDeclaration, propName, TRANSLATE_SERVICE_METHOD_NAMES);
|
|
||||||
callExpressions.forEach(callExpression => {
|
callExpressions.forEach(callExpression => {
|
||||||
const [firstArg] = callExpression.arguments;
|
const [firstArg] = callExpression.arguments;
|
||||||
if (!firstArg) {
|
if (!firstArg) {
|
||||||
@ -36,4 +36,21 @@ export class ServiceParser implements ParserInterface {
|
|||||||
});
|
});
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected findConstructorParamCallExpressions(classDeclaration: ClassDeclaration): CallExpression[] {
|
||||||
|
const constructorDeclaration = findConstructorDeclaration(classDeclaration);
|
||||||
|
if (!constructorDeclaration) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const paramName = findMethodParameterByType(constructorDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE);
|
||||||
|
return findMethodCallExpressions(constructorDeclaration, paramName, TRANSLATE_SERVICE_METHOD_NAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected findPropertyCallExpressions(classDeclaration: ClassDeclaration): CallExpression[] {
|
||||||
|
const propName: string = findClassPropertyByType(classDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE);
|
||||||
|
if (!propName) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return findPropertyCallExpressions(classDeclaration, propName, TRANSLATE_SERVICE_METHOD_NAMES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
import {
|
import {
|
||||||
|
SyntaxKind,
|
||||||
Node,
|
Node,
|
||||||
NamedImports,
|
NamedImports,
|
||||||
Identifier,
|
Identifier,
|
||||||
ClassDeclaration,
|
ClassDeclaration,
|
||||||
CallExpression,
|
ConstructorDeclaration,
|
||||||
isStringLiteralLike,
|
isStringLiteralLike,
|
||||||
isArrayLiteralExpression,
|
isArrayLiteralExpression,
|
||||||
|
CallExpression,
|
||||||
Expression,
|
Expression,
|
||||||
isBinaryExpression,
|
isBinaryExpression,
|
||||||
SyntaxKind,
|
|
||||||
isConditionalExpression,
|
isConditionalExpression,
|
||||||
PropertyAccessExpression
|
PropertyAccessExpression
|
||||||
} from 'typescript';
|
} from 'typescript';
|
||||||
@ -45,6 +46,30 @@ export function findClassPropertyByType(node: ClassDeclaration, type: string): s
|
|||||||
return findClassPropertyConstructorParameterByType(node, type) || findClassPropertyDeclarationByType(node, type);
|
return findClassPropertyConstructorParameterByType(node, type) || findClassPropertyDeclarationByType(node, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function findConstructorDeclaration(node: ClassDeclaration): ConstructorDeclaration {
|
||||||
|
const query = `Constructor`;
|
||||||
|
const [result] = tsquery<ConstructorDeclaration>(node, query);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findMethodParameterByType(node: Node, type: string): string | null {
|
||||||
|
const query = `Parameter:has(TypeReference > Identifier[name="${type}"]) > Identifier`;
|
||||||
|
const [result] = tsquery<Identifier>(node, query);
|
||||||
|
if (result) {
|
||||||
|
return result.text;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findMethodCallExpressions(node: Node, propName: string, fnName: string | string[]): CallExpression[] {
|
||||||
|
if (Array.isArray(fnName)) {
|
||||||
|
fnName = fnName.join('|');
|
||||||
|
}
|
||||||
|
const query = `CallExpression > PropertyAccessExpression:has(Identifier[name=/^(${fnName})$/]):has(PropertyAccessExpression:has(Identifier[name="${propName}"]):not(:has(ThisKeyword)))`;
|
||||||
|
const nodes = tsquery<PropertyAccessExpression>(node, query).map(n => n.parent as CallExpression);
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
export function findClassPropertyConstructorParameterByType(node: ClassDeclaration, type: string): string | null {
|
export function findClassPropertyConstructorParameterByType(node: ClassDeclaration, type: string): string | null {
|
||||||
const query = `Constructor Parameter:has(TypeReference > Identifier[name="${type}"]):has(PublicKeyword,ProtectedKeyword,PrivateKeyword) > Identifier`;
|
const query = `Constructor Parameter:has(TypeReference > Identifier[name="${type}"]):has(PublicKeyword,ProtectedKeyword,PrivateKeyword) > Identifier`;
|
||||||
const [result] = tsquery<Identifier>(node, query);
|
const [result] = tsquery<Identifier>(node, query);
|
||||||
@ -72,7 +97,7 @@ export function findFunctionCallExpressions(node: Node, fnName: string | string[
|
|||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findMethodCallExpressions(node: Node, prop: string, fnName: string | string[]): CallExpression[] {
|
export function findPropertyCallExpressions(node: Node, prop: string, fnName: string | string[]): CallExpression[] {
|
||||||
if (Array.isArray(fnName)) {
|
if (Array.isArray(fnName)) {
|
||||||
fnName = fnName.join('|');
|
fnName = fnName.join('|');
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,18 @@ describe('ServiceParser', () => {
|
|||||||
parser = new ServiceParser();
|
parser = new ServiceParser();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should extract strings when TranslateService is accessed directly via constructor parameter', () => {
|
||||||
|
const contents = `
|
||||||
|
@Component({ })
|
||||||
|
export class MyComponent {
|
||||||
|
public constructor(protected translateService: TranslateService) {
|
||||||
|
translateService.get('It works!');
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const keys = parser.extract(contents, componentFilename).keys();
|
||||||
|
expect(keys).to.deep.equal(['It works!']);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support extracting binary expressions', () => {
|
it('should support extracting binary expressions', () => {
|
||||||
const contents = `
|
const contents = `
|
||||||
@Component({ })
|
@Component({ })
|
||||||
|
Loading…
x
Reference in New Issue
Block a user