From 951dd5bd45fae9b1913cc97b107a2e3df7de19c2 Mon Sep 17 00:00:00 2001 From: Quramy Date: Fri, 15 Mar 2024 22:12:50 +0900 Subject: [PATCH] fix: Make transformer convert callExpression matching tag condition --- .../__snapshots__/transformer.test.ts.snap | 60 ++++++++++++++++ src/transformer/transformer.test.ts | 72 ++++++++++++++++++- src/transformer/transformer.ts | 12 ++-- 3 files changed, 135 insertions(+), 9 deletions(-) diff --git a/src/transformer/__snapshots__/transformer.test.ts.snap b/src/transformer/__snapshots__/transformer.test.ts.snap index d8624f3ba..8c2fe758c 100644 --- a/src/transformer/__snapshots__/transformer.test.ts.snap +++ b/src/transformer/__snapshots__/transformer.test.ts.snap @@ -15,6 +15,16 @@ exports[`transformer GraphQL document transformation should ignore TemplateExpre " `; +exports[`transformer GraphQL document transformation should ignore arguments which are not template literal in CallExpression node even if the node matches tag name 1`] = ` +"const query = hoge('abc', 100); +" +`; + +exports[`transformer GraphQL document transformation should ignore template argument in CallExpression when the node does not matche tag name 1`] = ` +"const query = hoge(\`abc\`); +" +`; + exports[`transformer GraphQL document transformation should transform NoSubstitutionTemplateLiteral 1`] = ` "const query = { kind: "Document", @@ -115,6 +125,56 @@ exports[`transformer GraphQL document transformation should transform TemplateEx " `; +exports[`transformer GraphQL document transformation should transform first template argument in CallExpression when the node matches tag name 1`] = ` +"const query = { + kind: "Document", + definitions: [{ + kind: "OperationDefinition", + operation: "query", + variableDefinitions: [], + directives: [], + selectionSet: { + kind: "SelectionSet", + selections: [{ + kind: "Field", + name: { + kind: "Name", + value: "hello" + }, + arguments: [], + directives: [] + }] + } + }] +}; +" +`; + +exports[`transformer GraphQL document transformation should transform first template expression argument in CallExpression when the node matches tag name 1`] = ` +"const query = { + kind: "Document", + definitions: [{ + kind: "OperationDefinition", + operation: "query", + variableDefinitions: [], + directives: [], + selectionSet: { + kind: "SelectionSet", + selections: [{ + kind: "Field", + name: { + kind: "Name", + value: "hello" + }, + arguments: [], + directives: [] + }] + } + }] +}; +" +`; + exports[`transformer GraphQL document transformation should transform inner document with documentTransformers 1`] = ` "const query = { kind: "Document", diff --git a/src/transformer/transformer.test.ts b/src/transformer/transformer.test.ts index a21ab7a23..8381a3a54 100644 --- a/src/transformer/transformer.test.ts +++ b/src/transformer/transformer.test.ts @@ -1,7 +1,7 @@ import ts from 'typescript'; import { DocumentNode, parse, visit } from 'graphql'; -import { parseTagConfig } from '../ts-ast-util'; +import { parseTagConfig, type TagConfig } from '../ts-ast-util'; import { getTransformer } from './transformer'; function transformAndPrint({ @@ -13,7 +13,7 @@ function transformAndPrint({ documentTransformers = [], enabled = true, }: { - tag?: string; + tag?: TagConfig; target: 'text' | 'object'; docContent: string; tsContent: string; @@ -153,6 +153,74 @@ describe('transformer', () => { ).toMatchSnapshot(); }); + it('should transform first template argument in CallExpression when the node matches tag name', () => { + expect( + transformAndPrint({ + tsContent: ` + const query = hoge(\`abc\`); + `, + tag: { name: 'hoge', ignoreFunctionCallExpression: false }, + docContent: ` + query { + hello + } + `, + target: 'object', + }), + ).toMatchSnapshot(); + }); + + it('should transform first template expression argument in CallExpression when the node matches tag name', () => { + expect( + transformAndPrint({ + tsContent: ` + const query = hoge(\`abc\${def}\`); + `, + tag: { name: 'hoge', ignoreFunctionCallExpression: false }, + docContent: ` + query { + hello + } + `, + target: 'object', + }), + ).toMatchSnapshot(); + }); + + it('should ignore template argument in CallExpression when the node does not matche tag name', () => { + expect( + transformAndPrint({ + tsContent: ` + const query = hoge(\`abc\`); + `, + tag: { name: 'foo', ignoreFunctionCallExpression: false }, + docContent: ` + query { + hello + } + `, + target: 'object', + }), + ).toMatchSnapshot(); + }); + + it('should ignore arguments which are not template literal in CallExpression node even if the node matches tag name', () => { + expect( + transformAndPrint({ + tsContent: ` + const query = hoge('abc', 100); + `, + tag: { name: 'hoge', ignoreFunctionCallExpression: false }, + docContent: ` + query { + hello + } + `, + target: 'object', + }), + ).toMatchSnapshot(); + }); + it('should transform to 0 literal when removeFragmentDefinitions: true and document has only fragments', () => { expect( transformAndPrint({ diff --git a/src/transformer/transformer.ts b/src/transformer/transformer.ts index e0c3271c1..6f724c5f4 100644 --- a/src/transformer/transformer.ts +++ b/src/transformer/transformer.ts @@ -44,18 +44,16 @@ export function getTransformer({ return (ctx: ts.TransformationContext) => { const visit = (node: ts.Node): ts.Node | undefined => { if (!getEnabled()) return node; - if (tag.names.length > 1) return node; let templateNode: ts.NoSubstitutionTemplateLiteral | ts.TemplateExpression | undefined = undefined; - if (ts.isImportDeclaration(node) && tag.names[0]) { - return removeAliasFromImportDeclaration(node, tag.names[0]); + if (ts.isImportDeclaration(node) && tag.names.length > 0) { + return removeAliasFromImportDeclaration(node, tag.names); } - if ( - ts.isTaggedTemplateExpression(node) && - (!tag.names.length || !!getTemplateNodeUnder(node, { ...tag, allowFunctionCallExpression: false })) - ) { + if (ts.isTaggedTemplateExpression(node) && (!tag.names.length || !!getTemplateNodeUnder(node, tag))) { templateNode = node.template; + } else if (ts.isCallExpression(node) && !!getTemplateNodeUnder(node, tag)) { + templateNode = node.arguments[0] as ts.TemplateLiteral; } else if (tag.allowNotTaggedTemplate && ts.isNoSubstitutionTemplateLiteral(node)) { templateNode = node; } else if (tag.allowNotTaggedTemplate && ts.isTemplateExpression(node)) {