idlize
729 строк · 25.7 Кб
1/*
2* Copyright (c) 2024 Huawei Device Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15import { IndentedPrinter } from "../IndentedPrinter"
16import { asString, identName, importTypeName, typeName } from "../util"
17import { PeerGeneratorVisitor, RuntimeType } from "./PeerGeneratorVisitor"
18import * as ts from "typescript"
19
20let uniqueCounter = 0
21
22export interface ArgConvertor {
23tsTypeName: string
24isScoped: boolean
25useArray: boolean
26runtimeTypes: RuntimeType[]
27estimateSize(): number
28scopeStart?(param: string): string
29scopeEnd?(param: string): string
30convertorTSArg(param: string): string
31convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void
32convertorCArg(param: string): string
33convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void
34interopType(ts: boolean): string
35nativeType(): string
36param: string
37}
38
39export abstract class BaseArgConvertor implements ArgConvertor {
40constructor(
41public tsTypeName: string,
42public runtimeTypes: RuntimeType[],
43public isScoped: boolean,
44public useArray: boolean,
45public param: string
46) {}
47
48estimateSize(): number {
49return 0
50}
51nativeType(): string {
52return "Empty"
53}
54interopType(ts: boolean): string {
55return ts ? "object" : "void*"
56}
57
58scopeStart?(param: string): string
59scopeEnd?(param: string): string
60abstract convertorTSArg(param: string): string
61abstract convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void
62abstract convertorCArg(param: string): string
63abstract convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void
64}
65
66
67export class StringConvertor extends BaseArgConvertor {
68constructor(param: string) {
69super("string", [RuntimeType.STRING], false, false, param)
70}
71
72convertorTSArg(param: string): string {
73return param
74}
75convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
76printer.print(`${param}Serializer.writeString(${value})`)
77}
78convertorCArg(param: string): string {
79return `String(${param})`
80}
81convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
82printer.print(`${value} = ${param}Deserializer.readString();`)
83}
84
85nativeType(): string {
86return "String"
87}
88interopType(ts: boolean): string {
89return "KStringPtr"
90}
91estimateSize() {
92return 32
93}
94}
95
96export class BooleanConvertor extends BaseArgConvertor {
97constructor(param: string) {
98super("boolean", [RuntimeType.BOOLEAN, RuntimeType.NUMBER], false, false, param)
99// TODO: shall NUMBER be here?
100}
101
102convertorTSArg(param: string): string {
103return `+${param}`
104}
105convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
106printer.print(`${param}Serializer.writeBoolean(${value})`)
107}
108convertorCArg(param: string): string {
109return param
110}
111convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
112printer.print(`${value} = ${param}Deserializer.readBoolean();`)
113}
114
115nativeType(): string {
116return "KBoolean"
117}
118interopType(ts: boolean): string {
119return "KBoolean"
120}
121estimateSize() {
122return 1
123}
124}
125
126export class UndefinedConvertor extends BaseArgConvertor {
127constructor(param: string) {
128super("undefined", [RuntimeType.UNDEFINED], false, false, param)
129}
130
131convertorTSArg(param: string): string {
132return "nullptr"
133}
134convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
135printer.print(`${param}Serializer.writeUndefined()`)
136}
137convertorCArg(param: string): string {
138return param
139}
140convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
141printer.print(`${value} = ${param}Deserializer.readUndefined();`)
142}
143
144nativeType(): string {
145return "Undefined"
146}
147interopType(ts: boolean): string {
148return "KNativePointer"
149}
150
151estimateSize() {
152return 1
153}
154}
155
156export class EnumConvertor extends BaseArgConvertor {
157constructor(param: string, type: ts.TypeReferenceNode | ts.ImportTypeNode, visitor: PeerGeneratorVisitor) {
158// Enums are integers in runtime.
159super("number", [RuntimeType.NUMBER], false, false, param)
160const typeNameString = typeName(type)
161if (typeNameString) visitor.requestType(typeNameString, type)
162}
163
164convertorTSArg(param: string): string {
165// as unknown for non-int enums, so it wouldn't clutter compiler diagnostic
166return `${param} as unknown as int32`
167}
168convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
169// as unknown for non-int enums, so it wouldn't clutter compiler diagnostic
170printer.print(`${param}Serializer.writeInt32(${value} as unknown as int32)`)
171}
172convertorCArg(param: string): string {
173return param
174}
175convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
176printer.print(`${value} = ${param}Deserializer.readInt32();`)
177}
178
179nativeType(): string {
180return "KInt"
181}
182interopType(): string {
183return "KInt"
184}
185
186estimateSize() {
187return 4
188}
189}
190
191export class LengthConvertor extends BaseArgConvertor {
192constructor(param: string) {
193super("Length", [RuntimeType.NUMBER, RuntimeType.STRING, RuntimeType.OBJECT], false, true, param)
194}
195
196scopeStart(param: string): string {
197return `withLengthArray(${param}, (${param}Ptr) => {`
198}
199scopeEnd(param: string): string {
200return '})'
201}
202
203convertorTSArg(param: string): string {
204// return `${param}Ptr`
205throw new Error("Not used")
206}
207convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
208printer.print(`${param}Serializer.writeLength(${value})`)
209}
210convertorCArg(param: string): string {
211return `Length::fromArray(${param})`
212}
213convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
214printer.print(`${value} = ${param}Deserializer.readLength();`)
215}
216nativeType(): string {
217return "Length"
218}
219interopType(ts: boolean): string {
220return ts ? "Int32ArrayPtr" : "int32_t*"
221}
222estimateSize() {
223return 12
224}
225}
226
227export class UnionConvertor extends BaseArgConvertor {
228private memberConvertors: ArgConvertor[]
229
230constructor(param: string, visitor: PeerGeneratorVisitor, private type: ts.UnionTypeNode) {
231super(`any`, [], false, true, param)
232this.memberConvertors = type
233.types
234.map(member => visitor.typeConvertor(param, member))
235this.checkUniques(param, this.memberConvertors)
236this.runtimeTypes = this.memberConvertors.flatMap(it => it.runtimeTypes)
237}
238convertorTSArg(param: string): string {
239throw new Error("Do not use for union")
240}
241convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
242printer.print(`const ${value}_type = runtimeType(${value})`)
243// Save actual type being passed.
244printer.print(`${param}Serializer.writeInt8(${value}_type)`)
245this.memberConvertors.forEach((it, index) => {
246if (it.runtimeTypes.length == 0) {
247console.log(`WARNING: branch for ${it.nativeType()} was consumed`)
248return
249}
250let maybeElse = (index > 0 && this.memberConvertors[index - 1].runtimeTypes.length > 0) ? "else " : ""
251let maybeComma1 = (it.runtimeTypes.length > 1) ? "(" : ""
252let maybeComma2 = (it.runtimeTypes.length > 1) ? ")" : ""
253
254printer.print(`${maybeElse}if (${it.runtimeTypes.map(it => `${maybeComma1}RuntimeType.${RuntimeType[it]} == ${value}_type${maybeComma2}`).join(" || ")}) {`)
255printer.pushIndent()
256if (!(it instanceof UndefinedConvertor)) {
257// TODO: `as unknown` is temporary to workaround for string enums.
258let maybeAsUnknown = (it instanceof EnumConvertor) ? "as unknown " : ""
259printer.print(`const ${value}_${index}: ${it.tsTypeName} = ${value} ${maybeAsUnknown}as ${it.tsTypeName}`)
260it.convertorToTSSerial(param, `${value}_${index}`, printer)
261}
262printer.popIndent()
263printer.print(`}`)
264})
265}
266convertorCArg(param: string): string {
267throw new Error("Do not use for union")
268}
269convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
270// Save actual type being passed.
271let runtimeType = `runtimeType${uniqueCounter++}`;
272printer.print(`int32_t ${runtimeType} = ${param}Deserializer.readInt8();`)
273this.memberConvertors.forEach((it, index) => {
274if (it.runtimeTypes.length == 0) {
275return
276}
277let maybeElse = (index > 0 && this.memberConvertors[index - 1].runtimeTypes.length > 0) ? "else " : ""
278let maybeComma1 = (it.runtimeTypes.length > 1) ? "(" : ""
279let maybeComma2 = (it.runtimeTypes.length > 1) ? ")" : ""
280
281printer.print(`${maybeElse}if (${it.runtimeTypes.map(it => `${maybeComma1}RUNTIME_${RuntimeType[it]} == ${runtimeType}${maybeComma2}`).join(" || ")}) {`)
282printer.pushIndent()
283it.convertorToCDeserial(param, `${value}.value${index}`, printer)
284printer.print(`${value}.selector = ${index};`)
285printer.popIndent()
286printer.print(`}`)
287})
288}
289nativeType(): string {
290return `Union<${this.memberConvertors.map(it => it.nativeType()).join(", ")}>`
291}
292interopType(ts: boolean): string {
293throw new Error("Union")
294}
295estimateSize() {
296return 12
297}
298checkUniques(param: string, convertors: ArgConvertor[]): void {
299for (let i = 0; i < convertors.length; i++) {
300for (let j = i + 1; j < convertors.length; j++) {
301let first = convertors[i].runtimeTypes
302let second = convertors[j].runtimeTypes
303first.forEach(value => {
304let index = second.findIndex(it => it == value)
305if (index != -1) {
306console.log(`WARNING: Runtime type conflict in ${param}: could be ${RuntimeType[value]}`)
307second.splice(index, 1)
308}
309})
310}
311}
312}
313}
314
315export class ImportTypeConvertor extends BaseArgConvertor {
316private importedName: string
317constructor(param: string, visitor: PeerGeneratorVisitor, type: ts.ImportTypeNode) {
318super("Object", [RuntimeType.OBJECT], false, true, param)
319this.importedName = importTypeName(type)
320visitor.requestType(this.importedName, type)
321}
322
323convertorTSArg(param: string): string {
324throw new Error("Must never be used")
325}
326convertorCArg(param: string): string {
327throw new Error("Must never be used")
328}
329convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
330printer.print(`${param}Serializer.writeCustom("${this.importedName}", ${value})`)
331}
332convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
333printer.print(`${value} = ${param}Deserializer.readCustom("${this.importedName}");`)
334}
335nativeType(): string {
336return this.importedName
337}
338interopType(ts: boolean): string {
339throw new Error("Must never be used")
340}
341estimateSize() {
342return 32
343}
344}
345
346export class CustomTypeConvertor extends BaseArgConvertor {
347private customName: string
348constructor(param: string, visitor: PeerGeneratorVisitor, customName: string) {
349super("Object", [RuntimeType.OBJECT], false, true, param)
350this.customName = customName
351}
352
353convertorTSArg(param: string): string {
354throw new Error("Must never be used")
355}
356convertorCArg(param: string): string {
357throw new Error("Must never be used")
358}
359convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
360printer.print(`${param}Serializer.writeCustom("${this.customName}", ${value})`)
361}
362convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
363printer.print(`${value} = ${param}Deserializer.readCustom("${this.customName}");`)
364}
365nativeType(): string {
366return "CustomObject"
367}
368interopType(ts: boolean): string {
369throw new Error("Must never be used")
370}
371estimateSize() {
372return 32
373}
374}
375
376export class OptionConvertor extends BaseArgConvertor {
377private typeConvertor: ArgConvertor
378
379constructor(param: string, visitor: PeerGeneratorVisitor, type: ts.TypeNode) {
380let typeConvertor = visitor.typeConvertor(param, type)
381let runtimeTypes = typeConvertor.runtimeTypes;
382if (!runtimeTypes.includes(RuntimeType.UNDEFINED)) {
383runtimeTypes.push(RuntimeType.UNDEFINED)
384}
385super(`(${typeConvertor.tsTypeName})?`, runtimeTypes, typeConvertor.isScoped, true, param)
386this.typeConvertor = typeConvertor
387}
388
389convertorTSArg(param: string): string {
390throw new Error("Must never be used")
391}
392convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
393printer.print(`const ${value}_type = runtimeType(${value})`)
394printer.print(`${param}Serializer.writeInt8(${value}_type)`)
395printer.print(`if (${value}_type != RuntimeType.UNDEFINED) {`)
396printer.pushIndent()
397this.typeConvertor.convertorToTSSerial(param, value, printer)
398printer.popIndent()
399printer.print(`}`)
400}
401convertorCArg(param: string): string {
402throw new Error("Must never be used")
403}
404convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
405printer.print(`${value}.tag = ${param}Deserializer.readInt8() == RUNTIME_UNDEFINED ? TAG_UNDEFINED : TAG_OBJECT;`)
406printer.print(`if (${value}.tag != TAG_UNDEFINED) {`)
407printer.pushIndent()
408this.typeConvertor.convertorToCDeserial(param, `${value}.value`, printer)
409printer.popIndent()
410printer.print(`}`)
411}
412nativeType(): string {
413return `Tagged<${this.typeConvertor.nativeType()}>`
414}
415interopType(ts: boolean): string {
416return "KPointer"
417}
418estimateSize() {
419return this.typeConvertor.estimateSize()
420}
421}
422
423export class AggregateConvertor extends BaseArgConvertor {
424private memberConvertors: ArgConvertor[]
425private members: string[] = []
426
427constructor(param: string, visitor: PeerGeneratorVisitor, type: ts.TypeLiteralNode) {
428super(`any`, [RuntimeType.OBJECT], false, true, param)
429this.memberConvertors = type
430.members
431.filter(ts.isPropertySignature)
432.map((member, index) => {
433this.members[index] = identName(member.name)!
434return visitor.typeConvertor(param, member.type!, member.questionToken != undefined)
435})
436}
437
438convertorTSArg(param: string): string {
439throw new Error("Do not use for aggregates")
440}
441convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
442this.memberConvertors.forEach((it, index) => {
443let memberName = this.members[index]
444printer.print(`const ${value}_${memberName} = ${value}?.${memberName}`)
445it.convertorToTSSerial(param, `${value}_${memberName}`, printer)
446})
447}
448convertorCArg(param: string): string {
449throw new Error("Do not use")
450}
451convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
452this.memberConvertors.forEach((it, index) => {
453it.convertorToCDeserial(param, `${value}.value${index}`, printer)
454})
455}
456
457nativeType(): string {
458return `Compound<${this.memberConvertors.map(it => it.nativeType()).join(", ")}>`
459}
460interopType(): string {
461return "KNativePointer"
462}
463estimateSize() {
464return 4
465}
466}
467
468export class TypedConvertor extends BaseArgConvertor {
469constructor(
470name: string,
471private type: ts.TypeReferenceNode | undefined,
472param: string, protected visitor: PeerGeneratorVisitor) {
473super(name, [RuntimeType.OBJECT, RuntimeType.FUNCTION, RuntimeType.UNDEFINED], false, true, param)
474visitor.requestType(name, type)
475}
476
477convertorTSArg(param: string): string {
478throw new Error("Must never be used")
479}
480convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
481printer.print(`${param}Serializer.${this.visitor.serializerName(this.tsTypeName, this.type)}(${value})`)
482}
483convertorCArg(param: string): string {
484throw new Error("Must never be used")
485}
486convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
487printer.print(`${value} = ${param}Deserializer.${this.visitor.deserializerName(this.tsTypeName, this.type)}();`)
488}
489nativeType(): string {
490return this.tsTypeName
491}
492interopType(): string {
493throw new Error("Must never be used")
494}
495estimateSize() {
496return 12
497}
498}
499
500export class InterfaceConvertor extends TypedConvertor {
501constructor(name: string, param: string, visitor: PeerGeneratorVisitor, type: ts.TypeReferenceNode) {
502super(name, type, param, visitor)
503}
504}
505
506export class FunctionConvertor extends TypedConvertor {
507constructor(param: string, visitor: PeerGeneratorVisitor) {
508super("Function", undefined, param, visitor)
509}
510}
511
512export class TupleConvertor extends BaseArgConvertor {
513memberConvertors: ArgConvertor[]
514
515constructor(param: string, protected visitor: PeerGeneratorVisitor, private elementType: ts.TupleTypeNode) {
516super(`[${elementType.elements.map(it => visitor.mapType(it)).join(",")}]`, [RuntimeType.OBJECT], false, true, param)
517this.memberConvertors = elementType
518.elements
519.map(element => visitor.typeConvertor(param, element))
520}
521
522convertorTSArg(param: string): string {
523throw new Error("Must never be used")
524}
525
526convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
527printer.print(`${param}Serializer.writeInt8(runtimeType(${value}))`)
528printer.print(`if (${value} !== undefined) {`)
529printer.pushIndent()
530this.memberConvertors.forEach((it, index) => {
531printer.print(`const ${value}_${index} = ${value}[${index}]`)
532it.convertorToTSSerial(param, `${value}_${index}`, printer)
533})
534printer.popIndent()
535printer.print(`}`)
536}
537
538convertorCArg(param: string): string {
539throw new Error("Must never be used")
540}
541
542convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
543printer.print(`if ( ${param}Deserializer.readInt8() != RUNTIME_UNDEFINED) {`) // TODO: `else value = nullptr` ?
544printer.pushIndent()
545this.memberConvertors.forEach((it, index) => {
546it.convertorToCDeserial(param, `${value}.value${index}`, printer)
547})
548printer.popIndent()
549printer.print(`}`)
550}
551nativeType(): string {
552return mapCType(this.elementType)
553}
554interopType(ts: boolean): string {
555return "KNativePointer"
556}
557
558estimateSize() {
559return this.memberConvertors
560.map(it => it.estimateSize())
561.reduce((sum, current) => sum + current, 0)
562}
563}
564
565export class ArrayConvertor extends BaseArgConvertor {
566elementConvertor: ArgConvertor
567constructor(param: string, protected visitor: PeerGeneratorVisitor, private elementType: ts.TypeNode) {
568super(`Array<${visitor.mapType(elementType)}>`, [RuntimeType.OBJECT], false, true, param)
569this.elementConvertor = visitor.typeConvertor(param, elementType)
570}
571
572convertorTSArg(param: string): string {
573throw new Error("Must never be used")
574}
575convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
576// Array length.
577printer.print(`${param}Serializer.writeInt8(runtimeType(${value}))`)
578printer.print(`if (${value} !== undefined) {`)
579printer.pushIndent()
580printer.print(`${param}Serializer.writeInt32(${value}.length)`)
581printer.print(`for (let i = 0; i < ${value}.length; i++) {`)
582printer.pushIndent()
583printer.print(`const ${value}_element = ${value}[i]`)
584this.elementConvertor.convertorToTSSerial(param, `${value}_element`, printer)
585printer.popIndent()
586printer.print(`}`)
587printer.popIndent()
588printer.print(`}`)
589}
590convertorCArg(param: string): string {
591throw new Error("Must never be used")
592}
593convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
594// Array length.
595let runtimeType = `runtimeType${uniqueCounter++}`;
596let arrayLength = `arrayLength${uniqueCounter++}`;
597
598printer.print(`auto ${runtimeType} = ${param}Deserializer.readInt8();`)
599printer.print(`if (${runtimeType} != RUNTIME_UNDEFINED) {`) // TODO: `else value = nullptr` ?
600printer.pushIndent()
601printer.print(`auto ${arrayLength} = ${param}Deserializer.readInt32();`)
602printer.print(`${value}.resize(${arrayLength});`);
603printer.print(`for (int i = 0; i < ${arrayLength}; i++) {`)
604printer.pushIndent()
605this.elementConvertor.convertorToCDeserial(param, `${value}[i]`, printer)
606printer.popIndent()
607printer.print(`}`)
608printer.popIndent()
609printer.print(`}`)
610
611}
612nativeType(): string {
613return `Array<${mapCType(this.elementType)}>`
614}
615interopType(ts: boolean): string {
616return "KNativePointer"
617}
618estimateSize() {
619return 12
620}
621}
622export class NumberConvertor extends BaseArgConvertor {
623constructor(param: string) {
624// Enums are integers in runtime.
625super("number", [RuntimeType.NUMBER], false, false, param)
626}
627
628convertorTSArg(param: string): string {
629return param
630}
631convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
632printer.print(`${param}Serializer.writeNumber(${value})`)
633}
634convertorCArg(param: string): string {
635return `Number(${param})`
636}
637convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
638printer.print(`${value} = ${param}Deserializer.readNumber();`)
639}
640
641nativeType(): string {
642return "Number"
643}
644
645interopType(): string {
646return "KInt"
647}
648estimateSize() {
649return 4
650}
651}
652
653export class AnimationRangeConvertor extends BaseArgConvertor {
654constructor(param: string) {
655super("AnimationRange<number>", [RuntimeType.OBJECT, RuntimeType.UNDEFINED], false, true, param)
656}
657
658convertorTSArg(param: string): string {
659throw new Error("unused")
660}
661convertorToTSSerial(param: string, value: string, printer: IndentedPrinter): void {
662printer.print(`${param}Serializer.writeAnimationRange(${value});`)
663}
664convertorCArg(param: string): string {
665throw new Error("unused")
666}
667convertorToCDeserial(param: string, value: string, printer: IndentedPrinter): void {
668printer.print(`${value} = ${param}Deserializer.readAnimationRange();`)
669}
670nativeType(): string {
671return "Compound<Number, Number>" // TODO: figure out how to pass real type args
672}
673interopType(ts: boolean): string {
674return ts ? "Int32ArrayPtr" : "int32_t*"
675}
676estimateSize() {
677return 8
678}
679}
680
681function mapCType(type: ts.TypeNode): string {
682if (ts.isTypeReferenceNode(type)) {
683return identName(type.typeName)!
684}
685if (ts.isUnionTypeNode(type)) {
686return `Union<${type.types.map(it => mapCType(it)).join(", ")}>`
687}
688if (ts.isTypeLiteralNode(type)) {
689return `Compound<${type
690.members
691.filter(ts.isPropertySignature)
692.map(it => mapCType(it.type!))
693.join(", ")}>`
694}
695if (ts.isTupleTypeNode(type)) {
696return `Compound<${type
697.elements
698.map(it => mapCType(it))
699.join(", ")}>`
700}
701if (ts.isOptionalTypeNode(type)) {
702return `Tagged<${mapCType(type.type)}>`
703}
704if (ts.isFunctionTypeNode(type)) {
705return "Function"
706}
707if (ts.isParenthesizedTypeNode(type)) {
708return `${mapCType(type.type)}`
709}
710if (ts.isNamedTupleMember(type)) {
711return `${mapCType(type.type)}`
712}
713if (type.kind == ts.SyntaxKind.NumberKeyword) {
714return "Number"
715}
716if (type.kind == ts.SyntaxKind.StringKeyword) {
717return "String"
718}
719if (type.kind == ts.SyntaxKind.ObjectKeyword) {
720return "Object"
721}
722if (type.kind == ts.SyntaxKind.BooleanKeyword) {
723return "KBoolean"
724}
725if (type.kind == ts.SyntaxKind.AnyKeyword) {
726return "Any"
727}
728throw new Error(`Cannot map ${type.getText()}: ${type.kind}`)
729}
730