1import type { TSTypeKind } from "ast-types/gen/kinds"
2import type * as cs from "jscodeshift"
3
4//
5// this is needed to resolve a bug in jscodeshift that
6// forgets to traverse type parameters in call expressions
7//
8declare module "ast-types/gen/namedTypes.js" {
9 namespace namedTypes {
10 interface CallExpression extends TSHasOptionalTypeParameterInstantiation {}
11 }
12}
13
14export default function transformer(file: cs.FileInfo, api: cs.API) {
15 const j = api.jscodeshift
16
17 const root = j(file.source)
18
19 root.find(j.ExportNamedDeclaration, {
20 declaration: {
21 type: "VariableDeclaration",
22 declarations: [{
23 type: "VariableDeclarator",
24 id: {
25 type: "Identifier",
26 typeAnnotation: {
27 type: "TSTypeAnnotation",
28 typeAnnotation: {
29 type: "TSTypeLiteral",
30 members: [{ type: "TSCallSignatureDeclaration" }]
31 }
32 }
33 }
34 }]
35 }
36 }).forEach((path) => {
37 const comments = path.node.comments ?? []
38 j(path).find(j.TSCallSignatureDeclaration).forEach((path) => {
39 // Don't override comments if they already exist
40 if (hasComments(path.node)) return
41 path.node.comments = comments
42 })
43 })
44
45 root.find(j.ExportNamedDeclaration, {
46 declaration: {
47 type: "VariableDeclaration",
48 declarations: [{
49 type: "VariableDeclarator",
50 init: {
51 type: "CallExpression",
52 callee: {
53 type: "Identifier",
54 name: "dual"
55 }
56 }
57 }]
58 }
59 }).forEach((path) => {
60 const comments = path.node.comments ?? []
61 j(path).find(j.CallExpression).forEach((path) => {
62 path.node.typeParameters?.params.forEach((param) => {
63 // Don't override comments if they already exist
64 if (hasLeadingCommentRanges(param) || hasComments(param)) return
65 param.comments = comments
66 })
67 })
68 })
69
70 return root.toSource()
71}
72
73function hasComments(node: cs.Node) {
74 return Array.isArray(node.comments)
75}
76
77function hasLeadingCommentRanges(node: TSTypeKind) {
78 return "leadingComments" in node && Array.isArray(node.leadingComments) && node.leadingComments.length > 0
79}