Skip to content

Commit 1215ea5

Browse files
committed
fix(service-parser): ignore inject() calls for non-TranslateService types
Addresses the issue where calling methods like `inject(HttpClient).get(...)` incorrectly extracted strings as if they were translation keys. Closes #116
1 parent 8565ede commit 1215ea5

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

src/parsers/service.parser.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
getImportPath,
1818
findFunctionExpressions,
1919
findVariableNameByInjectType,
20+
findInlineInjectCallExpressions,
2021
getAST,
2122
getNamedImport
2223
} from '../utils/ast-helpers.js';
@@ -43,7 +44,8 @@ export class ServiceParser implements ParserInterface {
4344
functionDeclarations.forEach((fnDeclaration) => {
4445
const translateServiceVariableName = findVariableNameByInjectType(fnDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE);
4546
const callExpressions = findMethodCallExpressions(sourceFile, translateServiceVariableName, TRANSLATE_SERVICE_METHOD_NAMES);
46-
translateServiceCallExpressions.push(...callExpressions);
47+
const inlineInjectCallExpressions = findInlineInjectCallExpressions(sourceFile, TRANSLATE_SERVICE_TYPE_REFERENCE, TRANSLATE_SERVICE_METHOD_NAMES);
48+
translateServiceCallExpressions.push(...callExpressions, ...inlineInjectCallExpressions);
4749
});
4850

4951
classDeclarations.forEach((classDeclaration) => {
@@ -74,14 +76,14 @@ export class ServiceParser implements ParserInterface {
7476
}
7577
const paramName = findMethodParameterByType(constructorDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE);
7678
const methodCallExpressions = findMethodCallExpressions(constructorDeclaration, paramName, TRANSLATE_SERVICE_METHOD_NAMES);
77-
79+
const inlineInjectCallExpressions = findInlineInjectCallExpressions(constructorDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE, TRANSLATE_SERVICE_METHOD_NAMES)
7880
// Calls of the TranslateService when injected using the inject function within the constructor
7981
const translateServiceLocalVariableName = findVariableNameByInjectType(constructorDeclaration, TRANSLATE_SERVICE_TYPE_REFERENCE);
8082
const localVariableCallExpressions = translateServiceLocalVariableName
8183
? findMethodCallExpressions(constructorDeclaration, translateServiceLocalVariableName, TRANSLATE_SERVICE_METHOD_NAMES)
8284
: [];
8385

84-
return [...methodCallExpressions, ...localVariableCallExpressions];
86+
return [...methodCallExpressions, ...localVariableCallExpressions, ...inlineInjectCallExpressions];
8587
}
8688

8789
protected findPropertyCallExpressions(classDeclaration: ClassDeclaration, sourceFile: SourceFile): CallExpression[] {

src/utils/ast-helpers.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,19 @@ export function findMethodCallExpressions(node: Node, propName: string, fnName:
142142

143143
const fnNameRegex = functionNames.join('|');
144144

145-
const query = `CallExpression > PropertyAccessExpression:has(Identifier[name=/^(${fnNameRegex})$/]):has(PropertyAccessExpression:has(Identifier[name="${propName}"]):not(:has(ThisKeyword)), CallExpression:has(Identifier[name="inject"]))`;
145+
const query = `CallExpression > PropertyAccessExpression:has(Identifier[name=/^(${fnNameRegex})$/]):has(PropertyAccessExpression:has(Identifier[name="${propName}"]):not(:has(ThisKeyword)))`;
146+
147+
return tsquery(node, query)
148+
.filter((n) => functionNames.includes(n.getLastToken().getText()))
149+
.map((n) => n.parent as CallExpression);
150+
}
151+
152+
export function findInlineInjectCallExpressions(node: Node, injectType: string, fnName: string | string[]): CallExpression[] {
153+
const functionNames = typeof fnName === 'string' ? [fnName] : fnName;
154+
155+
const fnNameRegex = functionNames.join('|');
156+
157+
const query = `CallExpression > PropertyAccessExpression:has(Identifier[name=/^(${fnNameRegex})$/]):has(CallExpression:has(Identifier[name="inject"]):has(Identifier[name="${injectType}"]))`;
146158

147159
return tsquery(node, query)
148160
.filter((n) => functionNames.includes(n.getLastToken().getText()))

tests/parsers/service.parser.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,24 @@ describe('ServiceParser', () => {
383383
expect(keys).to.deep.equal(['key.instant', 'key.stream', 'key.get']);
384384
});
385385

386+
it('should extract strings when TranslateService is injected using the inject function inline within the constructor', () => {
387+
const contents = `
388+
export class MyComponent {
389+
readonly propInstant: string;
390+
readonly propStream: string;
391+
readonly propGet: string;
392+
393+
constructor() {
394+
this.propInstant = inject(TranslateService).instant('key.instant');
395+
this.propStream = inject(TranslateService).stream('key.stream');
396+
this.propGet = inject(TranslateService).get('key.get');
397+
}
398+
}
399+
`;
400+
const keys = parser.extract(contents, componentFilename)?.keys();
401+
expect(keys).to.deep.equal(['key.instant', 'key.stream', 'key.get']);
402+
});
403+
386404
it('should locate TranslateService when it is a JavaScript native private property', () => {
387405
const contents = `
388406
@Component({})
@@ -836,5 +854,20 @@ describe('ServiceParser', () => {
836854
const keys = parser.extract(contents, componentFilename)?.keys();
837855
expect(keys).to.deep.equal(['translation.key']);
838856
});
857+
858+
it('should ignore injected services that are not TranslateService type', () => {
859+
const contents = `
860+
import {inject} from '@angular/core';
861+
import {HttpClient} from '@angular/common/http';
862+
863+
export const getResource = (): string => {
864+
const someService = inject(SomeService).instant('property');
865+
const someStream = inject(SomeStreamService).stream('property');
866+
return inject(HttpClient).get('/path/to/resource/');
867+
}
868+
`;
869+
const keys = parser.extract(contents, componentFilename)?.keys();
870+
expect(keys).to.deep.equal([]);
871+
});
839872
});
840873
});

0 commit comments

Comments
 (0)