(feat) add support for extracting binary expressions. example: translateService.instant(message || 'text if message is falsey')

This commit is contained in:
Kim Biesbjerg 2019-06-12 15:04:47 +02:00
parent cb53f6f3b1
commit 02fc705bc0

View File

@ -1,65 +1,77 @@
import * as ts from 'typescript';
import {
createSourceFile,
SourceFile,
CallExpression,
Node,
SyntaxKind,
StringLiteral,
isStringLiteralLike,
isBinaryExpression,
isTemplateLiteralToken,
isArrayLiteralExpression
} from 'typescript';
import { yellow } from 'colorette';
export abstract class AbstractAstParser {
protected sourceFile: ts.SourceFile;
protected sourceFile: SourceFile;
protected createSourceFile(path: string, contents: string): ts.SourceFile {
return ts.createSourceFile(path, contents, null, /*setParentNodes */ false);
protected createSourceFile(path: string, contents: string): SourceFile {
return createSourceFile(path, contents, null, /*setParentNodes */ false);
}
/**
* Get strings from function call's first argument
*/
protected getCallArgStrings(callNode: ts.CallExpression): string[] {
protected getCallArgStrings(callNode: CallExpression): string[] {
if (!callNode.arguments.length) {
return;
}
const firstArg = callNode.arguments[0];
switch (firstArg.kind) {
case ts.SyntaxKind.StringLiteral:
case ts.SyntaxKind.FirstTemplateToken:
return [(firstArg as ts.StringLiteral).text];
case ts.SyntaxKind.ArrayLiteralExpression:
return (firstArg as ts.ArrayLiteralExpression).elements
.map((element: ts.StringLiteral) => element.text);
case ts.SyntaxKind.Identifier:
// TODO
console.log(yellow('[Line: %d] We do not support values passed to TranslateService'), this.getLine(firstArg));
break;
case ts.SyntaxKind.BinaryExpression:
// TODO
console.log(yellow('[Line: %d] We do not support binary expressions (yet)'), this.getLine(firstArg));
break;
default:
console.log(yellow(`[Line: %d] Unknown argument type: %s`), this.getLine(firstArg), this.syntaxKindToName(firstArg.kind), firstArg);
const node = callNode.arguments[0];
if (isStringLiteralLike(node) || isTemplateLiteralToken(node)) {
return [node.text];
}
if (isArrayLiteralExpression(node)) {
return node.elements
.map((element: StringLiteral) => element.text);
}
if (isBinaryExpression(node)) {
return [node.right]
.filter(childNode => isStringLiteralLike(childNode))
.map((childNode: StringLiteral) => childNode.text);
}
console.log(yellow(`Unsupported syntax kind in line %d: %s`), this.getLineNumber(node), this.syntaxKindToName(node.kind));
return [];
}
/**
* Find all child nodes of a kind
*/
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] : [];
protected findNodes(node: Node, kind: SyntaxKind): Node[] {
const childrenNodes: Node[] = node.getChildren(this.sourceFile);
const initialValue: Node[] = node.kind === kind ? [node] : [];
return childrenNodes.reduce((result: ts.Node[], childNode: ts.Node) => {
return childrenNodes.reduce((result: Node[], childNode: Node) => {
return result.concat(this.findNodes(childNode, kind));
}, initialValue);
}
protected getLine(node: ts.Node): number {
protected getLineNumber(node: Node): number {
const { line } = this.sourceFile.getLineAndCharacterOfPosition(node.pos);
return line + 1;
}
protected syntaxKindToName(kind: ts.SyntaxKind): string {
return ts.SyntaxKind[kind];
protected syntaxKindToName(kind: SyntaxKind): string {
return SyntaxKind[kind];
}
protected printAllChildren(sourceFile: ts.SourceFile, node: ts.Node, depth = 0): void {
protected printAllChildren(sourceFile: SourceFile, node: Node, depth = 0): void {
console.log(
new Array(depth + 1).join('----'),
`[${node.kind}]`,