ether-code 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/cli/ether.js +1 -1
  2. package/generators/css-generator.js +42 -55
  3. package/generators/graphql-generator.js +19 -22
  4. package/generators/html-generator.js +51 -220
  5. package/generators/js-generator.js +76 -157
  6. package/generators/node-generator.js +49 -93
  7. package/generators/php-generator.js +46 -68
  8. package/generators/python-generator.js +35 -54
  9. package/generators/react-generator.js +37 -47
  10. package/generators/ruby-generator.js +59 -119
  11. package/generators/sql-generator.js +42 -63
  12. package/generators/ts-generator.js +59 -133
  13. package/i18n/i18n-css.json +147 -147
  14. package/i18n/i18n-graphql.json +6 -6
  15. package/i18n/i18n-html.json +135 -135
  16. package/i18n/i18n-js.json +107 -107
  17. package/i18n/i18n-node.json +14 -14
  18. package/i18n/i18n-php.json +177 -177
  19. package/i18n/i18n-python.json +16 -16
  20. package/i18n/i18n-react.json +97 -97
  21. package/i18n/i18n-ruby.json +22 -22
  22. package/i18n/i18n-sql.json +153 -153
  23. package/i18n/i18n-ts.json +10 -10
  24. package/lexer/ether-lexer.js +175 -34
  25. package/lexer/tokens.js +6 -6
  26. package/package.json +1 -1
  27. package/parsers/ast-css.js +0 -545
  28. package/parsers/ast-graphql.js +0 -424
  29. package/parsers/ast-html.js +0 -886
  30. package/parsers/ast-js.js +0 -750
  31. package/parsers/ast-node.js +0 -2440
  32. package/parsers/ast-php.js +0 -957
  33. package/parsers/ast-react.js +0 -580
  34. package/parsers/ast-ruby.js +0 -895
  35. package/parsers/ast-ts.js +0 -1352
  36. package/parsers/css-parser.js +0 -1981
  37. package/parsers/graphql-parser.js +0 -2011
  38. package/parsers/html-parser.js +0 -1182
  39. package/parsers/js-parser.js +0 -2564
  40. package/parsers/node-parser.js +0 -2644
  41. package/parsers/php-parser.js +0 -3037
  42. package/parsers/react-parser.js +0 -1035
  43. package/parsers/ruby-parser.js +0 -2680
  44. package/parsers/ts-parser.js +0 -3881
@@ -1,3881 +0,0 @@
1
- const fs = require('fs')
2
- const AST = require('./ast-ts')
3
-
4
-
5
- const TS_KEYWORDS = {
6
- 'interface': 'interface', 'interfaz': 'interface', 'интерфейс': 'interface', '接口': 'interface', 'インターフェース': 'interface',
7
- 'type': 'type', 'tipo': 'type', 'тип': 'type', '类型': 'type', 'タイプ': 'type',
8
- 'enumeration': 'enum', 'énumération': 'enum', 'enum': 'enum', 'enumeracion': 'enum', 'enumeración': 'enum', 'перечисление': 'enum', '枚举': 'enum', '列挙': 'enum',
9
- 'espaceNom': 'namespace', 'namespace': 'namespace', 'espacioNombre': 'namespace', 'пространствоИмен': 'namespace', '命名空间': 'namespace', '名前空間': 'namespace',
10
- 'declarer': 'declare', 'déclarer': 'declare', 'declare': 'declare', 'declarar': 'declare', 'объявить': 'declare', '声明': 'declare', '宣言': 'declare',
11
- 'module': 'module', 'modulo': 'module', 'módulo': 'module', 'модуль': 'module', '模块': 'module', 'モジュール': 'module',
12
-
13
- 'public': 'public', 'publico': 'public', 'público': 'public', 'публичный': 'public', '公开': 'public', 'パブリック': 'public',
14
- 'prive': 'private', 'privé': 'private', 'private': 'private', 'privado': 'private', 'приватный': 'private', '私有': 'private', 'プライベート': 'private',
15
- 'protege': 'protected', 'protégé': 'protected', 'protected': 'protected', 'protegido': 'protected', 'защищенный': 'protected', '受保护': 'protected', 'プロテクト': 'protected',
16
- 'lectureSeule': 'readonly', 'readonly': 'readonly', 'soloLectura': 'readonly', 'толькоЧтение': 'readonly', '只读': 'readonly', '読み取り専用': 'readonly',
17
- 'statique': 'static', 'static': 'static', 'estatico': 'static', 'estático': 'static', 'статический': 'static', '静态': 'static', 'スタティック': 'static',
18
- 'abstrait': 'abstract', 'abstract': 'abstract', 'abstracto': 'abstract', 'абстрактный': 'abstract', '抽象': 'abstract', 'アブストラクト': 'abstract',
19
-
20
- 'etend': 'extends', 'étend': 'extends', 'extends': 'extends', 'extiende': 'extends', 'расширяет': 'extends', '扩展': 'extends', '拡張': 'extends',
21
- 'implemente': 'implements', 'implémente': 'implements', 'implements': 'implements', 'implementa': 'implements', 'реализует': 'implements', '实现': 'implements', '実装': 'implements',
22
- 'redefinir': 'override', 'redéfinir': 'override', 'override': 'override', 'anular': 'override', 'переопределить': 'override', '覆盖': 'override', 'オーバーライド': 'override',
23
-
24
- 'comme': 'as', 'as': 'as', 'como': 'as', 'как': 'as', '作为': 'as', 'として': 'as',
25
- 'est': 'is', 'is': 'is', 'es': 'is', 'является': 'is', '是': 'is', 'である': 'is',
26
- 'affirme': 'asserts', 'asserts': 'asserts', 'afirma': 'asserts', 'утверждает': 'asserts', '断言': 'asserts', 'アサート': 'asserts',
27
- 'satisfait': 'satisfies', 'satisfies': 'satisfies', 'satisface': 'satisfies', 'удовлетворяет': 'satisfies', '满足': 'satisfies', '満たす': 'satisfies',
28
-
29
- 'cleDe': 'keyof', 'cléDe': 'keyof', 'keyof': 'keyof', 'claveDe': 'keyof', 'ключ': 'keyof', '键类型': 'keyof', 'キー型': 'keyof',
30
- 'typeDe': 'typeof', 'typeof': 'typeof', 'tipoDe': 'typeof', 'типОт': 'typeof', '类型': 'typeof', 'タイプオブ': 'typeof',
31
- 'inferer': 'infer', 'inférer': 'infer', 'infer': 'infer', 'inferir': 'infer', 'выводить': 'infer', '推断': 'infer', '推論': 'infer',
32
-
33
- 'constructeur': 'constructor', 'constructor': 'constructor', 'конструктор': 'constructor', '构造函数': 'constructor', 'コンストラクタ': 'constructor',
34
- 'obtenir': 'get', 'get': 'get', 'obtener': 'get', 'получить': 'get', '获取': 'get', 'ゲット': 'get',
35
- 'definir': 'set', 'définir': 'set', 'set': 'set', 'establecer': 'set', 'установить': 'set', '设置': 'set', 'セット': 'set',
36
-
37
- 'si': 'if', 'if': 'if', 'если': 'if', '如果': 'if', 'もし': 'if',
38
- 'sinon': 'else', 'else': 'else', 'sino': 'else', 'иначе': 'else', '否则': 'else', 'そうでなければ': 'else',
39
- 'pour': 'for', 'for': 'for', 'para': 'for', 'для': 'for', '为': 'for', 'ため': 'for',
40
- 'tant que': 'while', 'while': 'while', 'mientras': 'while', 'пока': 'while', '当': 'while', 'の間': 'while',
41
- 'faire': 'do', 'do': 'do', 'hacer': 'do', 'делать': 'do', '做': 'do', 'する': 'do',
42
- 'selon': 'switch', 'switch': 'switch', 'segun': 'switch', 'según': 'switch', 'переключатель': 'switch', '开关': 'switch', 'スイッチ': 'switch',
43
- 'cas': 'case', 'case': 'case', 'caso': 'case', 'случай': 'case', '情况': 'case', 'ケース': 'case',
44
- 'defaut': 'default', 'défaut': 'default', 'default': 'default', 'porDefecto': 'default', 'поумолчанию': 'default', '默认': 'default', 'デフォルト': 'default',
45
- 'continuer': 'continue', 'continue': 'continue', 'continuar': 'continue', 'продолжить': 'continue', '继续': 'continue', '続ける': 'continue',
46
- 'sortir': 'break', 'break': 'break', 'romper': 'break', 'прервать': 'break', '中断': 'break', 'ブレーク': 'break',
47
- 'retourner': 'return', 'return': 'return', 'retornar': 'return', 'возвращать': 'return', '返回': 'return', '戻る': 'return',
48
-
49
- 'fonction': 'function', 'function': 'function', 'funcion': 'function', 'función': 'function', 'функция': 'function', '函数': 'function', '関数': 'function',
50
- 'classe': 'class', 'class': 'class', 'clase': 'class', 'класс': 'class', '类': 'class', 'クラス': 'class',
51
- 'nouveau': 'new', 'new': 'new', 'nuevo': 'new', 'новый': 'new', '新建': 'new', '新規': 'new',
52
-
53
- 'constante': 'const', 'const': 'const', 'константа': 'const', '常量': 'const', '定数': 'const',
54
- 'variable': 'let', 'let': 'let', 'переменная': 'let', '变量': 'let', '変数': 'let',
55
- 'var': 'var',
56
-
57
- 'essayer': 'try', 'try': 'try', 'intentar': 'try', 'попробовать': 'try', '尝试': 'try', 'トライ': 'try',
58
- 'attraper': 'catch', 'catch': 'catch', 'capturar': 'catch', 'поймать': 'catch', '捕获': 'catch', 'キャッチ': 'catch',
59
- 'enfin': 'finally', 'finally': 'finally', 'finalmente': 'finally', 'наконец': 'finally', '最终': 'finally', 'ファイナリー': 'finally',
60
- 'lancer': 'throw', 'throw': 'throw', 'lanzar': 'throw', 'бросить': 'throw', '抛出': 'throw', 'スロー': 'throw',
61
-
62
- 'importer': 'import', 'import': 'import', 'importar': 'import', 'импортировать': 'import', '导入': 'import', 'インポート': 'import',
63
- 'exporter': 'export', 'export': 'export', 'exportar': 'export', 'экспортировать': 'export', '导出': 'export', 'エクスポート': 'export',
64
- 'depuis': 'from', 'from': 'from', 'desde': 'from', 'из': 'from', '从': 'from', 'から': 'from',
65
-
66
- 'asynchrone': 'async', 'async': 'async', 'asincrono': 'async', 'asíncrono': 'async', 'асинхронный': 'async', '异步': 'async', '非同期': 'async',
67
- 'attendre': 'await', 'await': 'await', 'esperar': 'await', 'ожидать': 'await', '等待': 'await', '待つ': 'await',
68
-
69
- 'vrai': 'true', 'true': 'true', 'verdadero': 'true', 'истина': 'true', '真': 'true', '真実': 'true',
70
- 'faux': 'false', 'false': 'false', 'falso': 'false', 'ложь': 'false', '假': 'false', '偽': 'false',
71
- 'nul': 'null', 'null': 'null', 'nulo': 'null', 'ноль': 'null', '空': 'null', 'ヌル': 'null',
72
- 'indefini': 'undefined', 'indéfini': 'undefined', 'undefined': 'undefined', 'indefinido': 'undefined', 'неопределено': 'undefined', '未定义': 'undefined', '未定義': 'undefined',
73
-
74
- 'dans': 'in', 'in': 'in', 'en': 'in', 'в': 'in', '在': 'in', 'の中': 'in',
75
- 'de': 'of', 'of': 'of', 'от': 'of', '的': 'of', 'の': 'of',
76
- 'instanceDe': 'instanceof', 'instanceof': 'instanceof', 'instanciaDe': 'instanceof', 'экземпляр': 'instanceof', '实例': 'instanceof', 'インスタンス': 'instanceof',
77
- 'supprimer': 'delete', 'delete': 'delete', 'eliminar': 'delete', 'удалить': 'delete', '删除': 'delete', '削除': 'delete',
78
-
79
- 'soi': 'this', 'this': 'this', 'esto': 'this', 'это': 'this', '这': 'this', 'これ': 'this',
80
- 'super': 'super', 'супер': 'super', '超级': 'super', 'スーパー': 'super',
81
-
82
- 'ou': 'or', 'or': 'or', 'o': 'or', 'или': 'or', '或': 'or', 'または': 'or',
83
- 'et': 'and', 'and': 'and', 'y': 'and', 'и': 'and', '且': 'and', 'かつ': 'and'
84
- }
85
-
86
- const TS_TYPES = {
87
- 'chaine': 'string', 'chaîne': 'string', 'string': 'string', 'cadena': 'string', 'строка': 'string', '字符串': 'string', '文字列': 'string',
88
- 'nombre': 'number', 'number': 'number', 'numero': 'number', 'número': 'number', 'число': 'number', '数字': 'number', '数値': 'number',
89
- 'booleen': 'boolean', 'booléen': 'boolean', 'boolean': 'boolean', 'booleano': 'boolean', 'логический': 'boolean', '布尔': 'boolean', 'ブール': 'boolean',
90
- 'objet': 'object', 'object': 'object', 'objeto': 'object', 'объект': 'object', '对象': 'object', 'オブジェクト': 'object',
91
- 'symbole': 'symbol', 'symbol': 'symbol', 'simbolo': 'symbol', 'símbolo': 'symbol', 'символ': 'symbol', '符号': 'symbol', 'シンボル': 'symbol',
92
- 'grandEntier': 'bigint', 'bigint': 'bigint', 'enteroGrande': 'bigint', 'большоеЦелое': 'bigint', '大整数': 'bigint', 'ビッグイント': 'bigint',
93
-
94
- 'quelconque': 'any', 'any': 'any', 'cualquier': 'any', 'любой': 'any', '任意': 'any', '任意型': 'any',
95
- 'inconnu': 'unknown', 'unknown': 'unknown', 'desconocido': 'unknown', 'неизвестный': 'unknown', '未知': 'unknown', '不明': 'unknown',
96
- 'jamais': 'never', 'never': 'never', 'nunca': 'never', 'никогда': 'never', '永不': 'never', '決して': 'never',
97
- 'vide': 'void', 'void': 'void', 'vacio': 'void', 'vacío': 'void', 'пустой': 'void', '空': 'void', 'ボイド': 'void',
98
-
99
- 'Tableau': 'Array', 'Array': 'Array', 'Arreglo': 'Array', 'Массив': 'Array', '数组': 'Array', '配列': 'Array',
100
- 'Promesse': 'Promise', 'Promise': 'Promise', 'Promesa': 'Promise', 'Промис': 'Promise', '承诺': 'Promise', 'プロミス': 'Promise',
101
- 'Ensemble': 'Set', 'Set': 'Set', 'Conjunto': 'Set', 'Набор': 'Set', '集合': 'Set', 'セット': 'Set',
102
- 'Map': 'Map', 'Carte': 'Map', 'Mapa': 'Map', 'Карта': 'Map', '映射': 'Map', 'マップ': 'Map',
103
-
104
- 'Partiel': 'Partial', 'Partial': 'Partial', 'Parcial': 'Partial', 'Частичный': 'Partial', '部分': 'Partial', '部分的': 'Partial',
105
- 'Requis': 'Required', 'Required': 'Required', 'Requerido': 'Required', 'Обязательный': 'Required', '必需': 'Required', '必須': 'Required',
106
- 'LectureSeule': 'Readonly', 'Readonly': 'Readonly', 'SoloLectura': 'Readonly', 'ТолькоЧтение': 'Readonly', '只读类型': 'Readonly', '読み取り専用型': 'Readonly',
107
- 'Choisir': 'Pick', 'Pick': 'Pick', 'Elegir': 'Pick', 'Выбрать': 'Pick', '选取': 'Pick', 'ピック': 'Pick',
108
- 'Omettre': 'Omit', 'Omit': 'Omit', 'Omitir': 'Omit', 'Опустить': 'Omit', '省略': 'Omit', 'オミット': 'Omit',
109
- 'Exclure': 'Exclude', 'Exclude': 'Exclude', 'Excluir': 'Exclude', 'Исключить': 'Exclude', '排除': 'Exclude', '除外': 'Exclude',
110
- 'Extraire': 'Extract', 'Extract': 'Extract', 'Extraer': 'Extract', 'Извлечь': 'Extract', '提取': 'Extract', '抽出': 'Extract',
111
- 'NonNul': 'NonNullable', 'NonNullable': 'NonNullable', 'NoNulo': 'NonNullable', 'НеНулевой': 'NonNullable', '非空': 'NonNullable', '非ヌル': 'NonNullable',
112
- 'TypeRetour': 'ReturnType', 'ReturnType': 'ReturnType', 'TipoRetorno': 'ReturnType', 'ТипВозврата': 'ReturnType', '返回类型': 'ReturnType', '戻り型': 'ReturnType',
113
- 'Parametres': 'Parameters', 'Paramètres': 'Parameters', 'Parameters': 'Parameters', 'Parametros': 'Parameters', 'Parámetros': 'Parameters', 'Параметры': 'Parameters', '参数': 'Parameters', 'パラメータ': 'Parameters',
114
- 'TypeInstance': 'InstanceType', 'InstanceType': 'InstanceType', 'TipoInstancia': 'InstanceType', 'ТипЭкземпляра': 'InstanceType', '实例类型': 'InstanceType', 'インスタンス型': 'InstanceType',
115
- 'Enregistrement': 'Record', 'Record': 'Record', 'Registro': 'Record', 'Запись': 'Record', '记录': 'Record', 'レコード': 'Record',
116
- 'Attendu': 'Awaited', 'Awaited': 'Awaited', 'Esperado': 'Awaited', 'Ожидаемый': 'Awaited', '等待': 'Awaited', '待機': 'Awaited',
117
- 'Majuscule': 'Uppercase', 'Uppercase': 'Uppercase', 'Mayuscula': 'Uppercase', 'Mayúscula': 'Uppercase', 'Верхний': 'Uppercase', '大写': 'Uppercase', '大文字': 'Uppercase',
118
- 'Minuscule': 'Lowercase', 'Lowercase': 'Lowercase', 'Minuscula': 'Lowercase', 'Minúscula': 'Lowercase', 'Нижний': 'Lowercase', '小写': 'Lowercase', '小文字': 'Lowercase',
119
- 'Capitaliser': 'Capitalize', 'Capitalize': 'Capitalize', 'Capitalizar': 'Capitalize', 'Капитализировать': 'Capitalize', '首字母大写': 'Capitalize', '先頭大文字': 'Capitalize',
120
- 'Decapitaliser': 'Uncapitalize', 'Décapitaliser': 'Uncapitalize', 'Uncapitalize': 'Uncapitalize', 'Descapitalizar': 'Uncapitalize', 'Декапитализировать': 'Uncapitalize', '首字母小写': 'Uncapitalize', '先頭小文字': 'Uncapitalize'
121
- }
122
-
123
- class TSLexer {
124
- constructor(source, i18n = {}) {
125
- this.source = source
126
- this.pos = 0
127
- this.line = 1
128
- this.column = 1
129
- this.tokens = []
130
- this.i18n = i18n
131
- }
132
-
133
- peek(offset = 0) {
134
- return this.source[this.pos + offset] || ''
135
- }
136
-
137
- advance() {
138
- const char = this.source[this.pos]
139
- this.pos++
140
- if (char === '\n') {
141
- this.line++
142
- this.column = 1
143
- } else {
144
- this.column++
145
- }
146
- return char
147
- }
148
-
149
- skipWhitespace() {
150
- while (this.pos < this.source.length && /\s/.test(this.peek())) {
151
- this.advance()
152
- }
153
- }
154
-
155
- skipComment() {
156
- if (this.peek() === '/' && this.peek(1) === '/') {
157
- while (this.pos < this.source.length && this.peek() !== '\n') {
158
- this.advance()
159
- }
160
- return true
161
- }
162
- if (this.peek() === '/' && this.peek(1) === '*') {
163
- this.advance()
164
- this.advance()
165
- while (this.pos < this.source.length) {
166
- if (this.peek() === '*' && this.peek(1) === '/') {
167
- this.advance()
168
- this.advance()
169
- break
170
- }
171
- this.advance()
172
- }
173
- return true
174
- }
175
- return false
176
- }
177
-
178
- tokenize() {
179
- while (this.pos < this.source.length) {
180
- this.skipWhitespace()
181
- while (this.skipComment()) {
182
- this.skipWhitespace()
183
- }
184
- if (this.pos >= this.source.length) break
185
-
186
- const loc = { line: this.line, column: this.column }
187
- const char = this.peek()
188
-
189
- if (char === '"' || char === "'" || char === '`') {
190
- this.tokens.push(this.readString(char))
191
- continue
192
- }
193
-
194
- if (/[0-9]/.test(char) || (char === '.' && /[0-9]/.test(this.peek(1)))) {
195
- this.tokens.push(this.readNumber())
196
- continue
197
- }
198
-
199
- if (/[a-zA-ZÀ-ÿА-яぁ-ゟァ-ヿ一-龯_$]/.test(char)) {
200
- this.tokens.push(this.readWord())
201
- continue
202
- }
203
-
204
- if (char === '@') {
205
- this.advance()
206
- this.tokens.push({ type: 'AT', value: '@', loc })
207
- continue
208
- }
209
-
210
- if (char === '#') {
211
- this.advance()
212
- const name = this.readIdentifier()
213
- this.tokens.push({ type: 'PRIVATE_IDENTIFIER', value: name, loc })
214
- continue
215
- }
216
-
217
- const token = this.readOperator()
218
- if (token) {
219
- this.tokens.push(token)
220
- continue
221
- }
222
-
223
- this.advance()
224
- }
225
-
226
- this.tokens.push({ type: 'EOF', loc: { line: this.line, column: this.column } })
227
- return this.tokens
228
- }
229
-
230
- readIdentifier() {
231
- let name = ''
232
- while (this.pos < this.source.length && /[a-zA-Z0-9À-ÿА-яぁ-ゟァ-ヿ一-龯_$]/.test(this.peek())) {
233
- name += this.advance()
234
- }
235
- return name
236
- }
237
-
238
- readWord() {
239
- const loc = { line: this.line, column: this.column }
240
- let word = this.readIdentifier()
241
-
242
- const lowerWord = word.toLowerCase()
243
-
244
- if (TS_KEYWORDS[word] || TS_KEYWORDS[lowerWord]) {
245
- return { type: 'KEYWORD', value: word, loc }
246
- }
247
-
248
- if (TS_TYPES[word] || TS_TYPES[lowerWord]) {
249
- return { type: 'TYPE', value: word, loc }
250
- }
251
-
252
- return { type: 'IDENTIFIER', value: word, loc }
253
- }
254
-
255
- readString(quote) {
256
- const loc = { line: this.line, column: this.column }
257
- this.advance()
258
-
259
- if (quote === '`') {
260
- return this.readTemplateLiteral(loc)
261
- }
262
-
263
- let value = ''
264
- let raw = quote
265
-
266
- while (this.pos < this.source.length && this.peek() !== quote) {
267
- if (this.peek() === '\\') {
268
- raw += this.advance()
269
- if (this.pos < this.source.length) {
270
- const escaped = this.advance()
271
- raw += escaped
272
- switch (escaped) {
273
- case 'n': value += '\n'; break
274
- case 'r': value += '\r'; break
275
- case 't': value += '\t'; break
276
- case '\\': value += '\\'; break
277
- case quote: value += quote; break
278
- default: value += '\\' + escaped
279
- }
280
- }
281
- } else {
282
- const c = this.advance()
283
- value += c
284
- raw += c
285
- }
286
- }
287
-
288
- if (this.peek() === quote) {
289
- raw += this.advance()
290
- }
291
-
292
- return { type: 'STRING', value, raw, loc }
293
- }
294
-
295
- readTemplateLiteral(loc) {
296
- const quasis = []
297
- const expressions = []
298
- let current = ''
299
- let raw = '`'
300
-
301
- while (this.pos < this.source.length) {
302
- if (this.peek() === '`') {
303
- raw += this.advance()
304
- quasis.push({ value: current, tail: true })
305
- break
306
- }
307
-
308
- if (this.peek() === '$' && this.peek(1) === '{') {
309
- quasis.push({ value: current, tail: false })
310
- current = ''
311
- raw += this.advance() + this.advance()
312
-
313
- let braceCount = 1
314
- let expr = ''
315
- while (braceCount > 0 && this.pos < this.source.length) {
316
- const c = this.peek()
317
- if (c === '{') braceCount++
318
- if (c === '}') braceCount--
319
- if (braceCount > 0) {
320
- expr += this.advance()
321
- } else {
322
- raw += this.advance()
323
- }
324
- }
325
- expressions.push(expr)
326
- } else if (this.peek() === '\\') {
327
- raw += this.advance()
328
- if (this.pos < this.source.length) {
329
- const escaped = this.advance()
330
- raw += escaped
331
- switch (escaped) {
332
- case 'n': current += '\n'; break
333
- case 'r': current += '\r'; break
334
- case 't': current += '\t'; break
335
- default: current += escaped
336
- }
337
- }
338
- } else {
339
- const c = this.advance()
340
- current += c
341
- raw += c
342
- }
343
- }
344
-
345
- return { type: 'TEMPLATE', quasis, expressions, raw, loc }
346
- }
347
-
348
- readNumber() {
349
- const loc = { line: this.line, column: this.column }
350
- let value = ''
351
- let isBigInt = false
352
-
353
- if (this.peek() === '0' && (this.peek(1) === 'x' || this.peek(1) === 'X')) {
354
- value += this.advance() + this.advance()
355
- while (/[0-9a-fA-F_]/.test(this.peek())) {
356
- value += this.advance()
357
- }
358
- } else if (this.peek() === '0' && (this.peek(1) === 'b' || this.peek(1) === 'B')) {
359
- value += this.advance() + this.advance()
360
- while (/[01_]/.test(this.peek())) {
361
- value += this.advance()
362
- }
363
- } else if (this.peek() === '0' && (this.peek(1) === 'o' || this.peek(1) === 'O')) {
364
- value += this.advance() + this.advance()
365
- while (/[0-7_]/.test(this.peek())) {
366
- value += this.advance()
367
- }
368
- } else {
369
- while (/[0-9_]/.test(this.peek())) {
370
- value += this.advance()
371
- }
372
-
373
- if (this.peek() === '.' && /[0-9]/.test(this.peek(1))) {
374
- value += this.advance()
375
- while (/[0-9_]/.test(this.peek())) {
376
- value += this.advance()
377
- }
378
- }
379
-
380
- if (this.peek() === 'e' || this.peek() === 'E') {
381
- value += this.advance()
382
- if (this.peek() === '+' || this.peek() === '-') {
383
- value += this.advance()
384
- }
385
- while (/[0-9_]/.test(this.peek())) {
386
- value += this.advance()
387
- }
388
- }
389
- }
390
-
391
- if (this.peek() === 'n') {
392
- isBigInt = true
393
- this.advance()
394
- }
395
-
396
- const cleanValue = value.replace(/_/g, '')
397
-
398
- if (isBigInt) {
399
- return { type: 'BIGINT', value: cleanValue, raw: value + 'n', loc }
400
- }
401
-
402
- return {
403
- type: 'NUMBER',
404
- value: cleanValue.includes('.') || cleanValue.includes('e') || cleanValue.includes('E')
405
- ? parseFloat(cleanValue)
406
- : parseInt(cleanValue, value.startsWith('0x') ? 16 : value.startsWith('0b') ? 2 : value.startsWith('0o') ? 8 : 10),
407
- raw: value,
408
- loc
409
- }
410
- }
411
-
412
- readOperator() {
413
- const loc = { line: this.line, column: this.column }
414
-
415
- const fourChar = this.source.slice(this.pos, this.pos + 4)
416
- const threeChar = this.source.slice(this.pos, this.pos + 3)
417
- const twoChar = this.source.slice(this.pos, this.pos + 2)
418
- const oneChar = this.peek()
419
-
420
- const fourCharOps = { '>>>=': 'UNSIGNED_RIGHT_SHIFT_ASSIGN' }
421
-
422
- const threeCharOps = {
423
- '===': 'STRICT_EQUAL', '!==': 'STRICT_NOT_EQUAL',
424
- '...': 'SPREAD', '>>>': 'UNSIGNED_RIGHT_SHIFT',
425
- '**=': 'POW_ASSIGN', '&&=': 'AND_ASSIGN', '||=': 'OR_ASSIGN', '??=': 'NULLISH_ASSIGN',
426
- '<<=': 'LEFT_SHIFT_ASSIGN', '>>=': 'RIGHT_SHIFT_ASSIGN'
427
- }
428
-
429
- const twoCharOps = {
430
- '==': 'EQUAL', '!=': 'NOT_EQUAL',
431
- '<=': 'LTE', '>=': 'GTE',
432
- '&&': 'AND', '||': 'OR', '??': 'NULLISH',
433
- '++': 'INCREMENT', '--': 'DECREMENT',
434
- '**': 'POW', '<<': 'LEFT_SHIFT', '>>': 'RIGHT_SHIFT',
435
- '+=': 'PLUS_ASSIGN', '-=': 'MINUS_ASSIGN', '*=': 'TIMES_ASSIGN', '/=': 'DIV_ASSIGN', '%=': 'MOD_ASSIGN',
436
- '&=': 'BIT_AND_ASSIGN', '|=': 'BIT_OR_ASSIGN', '^=': 'BIT_XOR_ASSIGN',
437
- '=>': 'ARROW', '?.': 'OPTIONAL_CHAIN',
438
- '?.': 'OPTIONAL_CHAIN'
439
- }
440
-
441
- const oneCharOps = {
442
- '+': 'PLUS', '-': 'MINUS', '*': 'TIMES', '/': 'DIV', '%': 'MOD',
443
- '=': 'ASSIGN', '<': 'LT', '>': 'GT', '!': 'NOT', '~': 'TILDE',
444
- '&': 'BIT_AND', '|': 'BIT_OR', '^': 'BIT_XOR',
445
- '(': 'LPAREN', ')': 'RPAREN', '[': 'LBRACKET', ']': 'RBRACKET',
446
- '{': 'LBRACE', '}': 'RBRACE', ';': 'SEMICOLON', ':': 'COLON',
447
- ',': 'COMMA', '.': 'DOT', '?': 'QUESTION'
448
- }
449
-
450
- if (fourCharOps[fourChar]) {
451
- this.pos += 4
452
- return { type: fourCharOps[fourChar], value: fourChar, loc }
453
- }
454
-
455
- if (threeCharOps[threeChar]) {
456
- this.pos += 3
457
- return { type: threeCharOps[threeChar], value: threeChar, loc }
458
- }
459
-
460
- if (twoCharOps[twoChar]) {
461
- this.pos += 2
462
- return { type: twoCharOps[twoChar], value: twoChar, loc }
463
- }
464
-
465
- if (oneCharOps[oneChar]) {
466
- this.advance()
467
- return { type: oneCharOps[oneChar], value: oneChar, loc }
468
- }
469
-
470
- return null
471
- }
472
- }
473
-
474
- class TSParser {
475
- constructor(i18nPath = null) {
476
- this.tokens = []
477
- this.pos = 0
478
- this.i18n = {}
479
-
480
- if (i18nPath) {
481
- this.loadI18n(i18nPath)
482
- }
483
- }
484
-
485
- loadI18n(filePath) {
486
- try {
487
- const content = fs.readFileSync(filePath, 'utf-8')
488
- this.i18n = JSON.parse(content)
489
- } catch (e) {
490
- console.error(`Erreur chargement i18n: ${e.message}`)
491
- this.i18n = {}
492
- }
493
- }
494
-
495
- parse(source) {
496
- const lexer = new TSLexer(source, this.i18n)
497
- this.tokens = lexer.tokenize()
498
- this.pos = 0
499
- return this.parseProgram()
500
- }
501
-
502
- peek(offset = 0) {
503
- return this.tokens[this.pos + offset] || { type: 'EOF' }
504
- }
505
-
506
- advance() {
507
- return this.tokens[this.pos++]
508
- }
509
-
510
- match(...types) {
511
- return types.includes(this.peek().type)
512
- }
513
-
514
- expect(type) {
515
- const token = this.peek()
516
- if (token.type !== type) {
517
- throw new Error(`Attendu ${type}, reçu ${token.type} à ligne ${token.loc?.line}`)
518
- }
519
- return this.advance()
520
- }
521
-
522
- translateKeyword(word) {
523
- return TS_KEYWORDS[word] || TS_KEYWORDS[word.toLowerCase()] || word
524
- }
525
-
526
- translateType(word) {
527
- return TS_TYPES[word] || TS_TYPES[word.toLowerCase()] || word
528
- }
529
-
530
- parseProgram() {
531
- const body = []
532
-
533
- while (!this.match('EOF')) {
534
- const stmt = this.parseStatement()
535
- if (stmt) body.push(stmt)
536
- }
537
-
538
- return new AST.Program(body)
539
- }
540
-
541
- parseStatement() {
542
- const token = this.peek()
543
-
544
- if (token.type === 'AT') {
545
- return this.parseDecoratedDeclaration()
546
- }
547
-
548
- if (token.type === 'KEYWORD') {
549
- const kw = this.translateKeyword(token.value)
550
-
551
- switch (kw) {
552
- case 'interface': return this.parseInterfaceDeclaration()
553
- case 'type': return this.parseTypeAliasDeclaration()
554
- case 'enum': return this.parseEnumDeclaration()
555
- case 'namespace': return this.parseNamespaceDeclaration()
556
- case 'module': return this.parseModuleDeclaration()
557
- case 'declare': return this.parseDeclareStatement()
558
- case 'class': return this.parseClassDeclaration()
559
- case 'abstract': return this.parseAbstractClass()
560
- case 'function': return this.parseFunctionDeclaration()
561
- case 'const':
562
- case 'let':
563
- case 'var': return this.parseVariableDeclaration()
564
- case 'if': return this.parseIfStatement()
565
- case 'switch': return this.parseSwitchStatement()
566
- case 'for': return this.parseForStatement()
567
- case 'while': return this.parseWhileStatement()
568
- case 'do': return this.parseDoWhileStatement()
569
- case 'try': return this.parseTryStatement()
570
- case 'throw': return this.parseThrowStatement()
571
- case 'return': return this.parseReturnStatement()
572
- case 'break': return this.parseBreakStatement()
573
- case 'continue': return this.parseContinueStatement()
574
- case 'import': return this.parseImportDeclaration()
575
- case 'export': return this.parseExportDeclaration()
576
- case 'async': return this.parseAsyncFunction()
577
- }
578
- }
579
-
580
- if (this.match('LBRACE')) {
581
- return this.parseBlockStatement()
582
- }
583
-
584
- if (this.match('SEMICOLON')) {
585
- this.advance()
586
- return new AST.EmptyStatement(token.loc)
587
- }
588
-
589
- const expr = this.parseExpression()
590
- if (this.match('SEMICOLON')) this.advance()
591
-
592
- return new AST.ExpressionStatement(expr, token.loc)
593
- }
594
-
595
- parseInterfaceDeclaration() {
596
- const loc = this.peek().loc
597
- this.advance()
598
-
599
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
600
-
601
- let typeParameters = null
602
- if (this.match('LT')) {
603
- typeParameters = this.parseTypeParameters()
604
- }
605
-
606
- const extends_ = []
607
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'extends') {
608
- this.advance()
609
- extends_.push(this.parseInterfaceHeritage())
610
- while (this.match('COMMA')) {
611
- this.advance()
612
- extends_.push(this.parseInterfaceHeritage())
613
- }
614
- }
615
-
616
- const body = this.parseInterfaceBody()
617
-
618
- return new AST.TSInterfaceDeclaration(id, body, extends_, typeParameters, false, loc)
619
- }
620
-
621
- parseInterfaceHeritage() {
622
- const expression = this.parseIdentifierOrQualifiedName()
623
- let typeParameters = null
624
-
625
- if (this.match('LT')) {
626
- typeParameters = this.parseTypeArguments()
627
- }
628
-
629
- return new AST.TSInterfaceHeritage(expression, typeParameters)
630
- }
631
-
632
- parseInterfaceBody() {
633
- this.expect('LBRACE')
634
- const body = []
635
-
636
- while (!this.match('RBRACE', 'EOF')) {
637
- const member = this.parseTypeMember()
638
- if (member) body.push(member)
639
- if (this.match('SEMICOLON', 'COMMA')) this.advance()
640
- }
641
-
642
- this.expect('RBRACE')
643
- return new AST.TSInterfaceBody(body)
644
- }
645
-
646
- parseTypeMember() {
647
- const loc = this.peek().loc
648
- let readonly = false
649
- let optional = false
650
-
651
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'readonly') {
652
- readonly = true
653
- this.advance()
654
- }
655
-
656
- if (this.match('LBRACKET')) {
657
- return this.parseIndexSignature(readonly, loc)
658
- }
659
-
660
- if (this.match('LPAREN') || this.match('LT')) {
661
- return this.parseCallSignature()
662
- }
663
-
664
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'new') {
665
- return this.parseConstructSignature()
666
- }
667
-
668
- const key = this.parsePropertyName()
669
-
670
- if (this.match('QUESTION')) {
671
- this.advance()
672
- optional = true
673
- }
674
-
675
- if (this.match('LPAREN') || this.match('LT')) {
676
- return this.parseMethodSignature(key, optional, loc)
677
- }
678
-
679
- let typeAnnotation = null
680
- if (this.match('COLON')) {
681
- this.advance()
682
- typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
683
- }
684
-
685
- return new AST.TSPropertySignature(key, typeAnnotation, false, optional, readonly, loc)
686
- }
687
-
688
- parseIndexSignature(readonly, loc) {
689
- this.expect('LBRACKET')
690
-
691
- const parameters = []
692
- const paramName = this.expect('IDENTIFIER').value
693
- this.expect('COLON')
694
- const paramType = this.parseType()
695
- parameters.push({ name: paramName, type: paramType })
696
-
697
- this.expect('RBRACKET')
698
-
699
- let typeAnnotation = null
700
- if (this.match('COLON')) {
701
- this.advance()
702
- typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
703
- }
704
-
705
- return new AST.TSIndexSignature(parameters, typeAnnotation, readonly, false, loc)
706
- }
707
-
708
- parseCallSignature() {
709
- let typeParameters = null
710
- if (this.match('LT')) {
711
- typeParameters = this.parseTypeParameters()
712
- }
713
-
714
- this.expect('LPAREN')
715
- const params = this.parseParameterList()
716
- this.expect('RPAREN')
717
-
718
- let returnType = null
719
- if (this.match('COLON')) {
720
- this.advance()
721
- returnType = new AST.TSTypeAnnotation(this.parseType())
722
- }
723
-
724
- return new AST.TSCallSignatureDeclaration(params, returnType, typeParameters)
725
- }
726
-
727
- parseConstructSignature() {
728
- this.advance()
729
-
730
- let typeParameters = null
731
- if (this.match('LT')) {
732
- typeParameters = this.parseTypeParameters()
733
- }
734
-
735
- this.expect('LPAREN')
736
- const params = this.parseParameterList()
737
- this.expect('RPAREN')
738
-
739
- let returnType = null
740
- if (this.match('COLON')) {
741
- this.advance()
742
- returnType = new AST.TSTypeAnnotation(this.parseType())
743
- }
744
-
745
- return new AST.TSConstructSignatureDeclaration(params, returnType, typeParameters)
746
- }
747
-
748
- parseMethodSignature(key, optional, loc) {
749
- let typeParameters = null
750
- if (this.match('LT')) {
751
- typeParameters = this.parseTypeParameters()
752
- }
753
-
754
- this.expect('LPAREN')
755
- const params = this.parseParameterList()
756
- this.expect('RPAREN')
757
-
758
- let returnType = null
759
- if (this.match('COLON')) {
760
- this.advance()
761
- returnType = new AST.TSTypeAnnotation(this.parseType())
762
- }
763
-
764
- return new AST.TSMethodSignature(key, params, returnType, false, optional, typeParameters, loc)
765
- }
766
-
767
- parseTypeAliasDeclaration() {
768
- const loc = this.peek().loc
769
- this.advance()
770
-
771
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
772
-
773
- let typeParameters = null
774
- if (this.match('LT')) {
775
- typeParameters = this.parseTypeParameters()
776
- }
777
-
778
- this.expect('ASSIGN')
779
- const typeAnnotation = this.parseType()
780
-
781
- if (this.match('SEMICOLON')) this.advance()
782
-
783
- return new AST.TSTypeAliasDeclaration(id, typeAnnotation, typeParameters, false, loc)
784
- }
785
-
786
- parseEnumDeclaration() {
787
- const loc = this.peek().loc
788
- let const_ = false
789
-
790
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'const') {
791
- const_ = true
792
- this.advance()
793
- }
794
-
795
- this.advance()
796
-
797
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
798
-
799
- this.expect('LBRACE')
800
- const members = []
801
-
802
- while (!this.match('RBRACE', 'EOF')) {
803
- const memberName = this.expect('IDENTIFIER').value
804
- let initializer = null
805
-
806
- if (this.match('ASSIGN')) {
807
- this.advance()
808
- initializer = this.parseExpression()
809
- }
810
-
811
- members.push(new AST.TSEnumMember(new AST.Identifier(memberName), initializer))
812
-
813
- if (this.match('COMMA')) this.advance()
814
- }
815
-
816
- this.expect('RBRACE')
817
-
818
- return new AST.TSEnumDeclaration(id, members, const_, false, loc)
819
- }
820
-
821
- parseNamespaceDeclaration() {
822
- const loc = this.peek().loc
823
- this.advance()
824
-
825
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
826
-
827
- this.expect('LBRACE')
828
- const body = []
829
-
830
- while (!this.match('RBRACE', 'EOF')) {
831
- body.push(this.parseStatement())
832
- }
833
-
834
- this.expect('RBRACE')
835
-
836
- return new AST.TSModuleDeclaration(id, new AST.TSModuleBlock(body), false, false, loc)
837
- }
838
-
839
- parseModuleDeclaration() {
840
- return this.parseNamespaceDeclaration()
841
- }
842
-
843
- parseDeclareStatement() {
844
- const loc = this.peek().loc
845
- this.advance()
846
-
847
- const next = this.peek()
848
- if (next.type === 'KEYWORD') {
849
- const kw = this.translateKeyword(next.value)
850
-
851
- if (kw === 'function') {
852
- this.advance()
853
- return this.parseDeclareFunction(loc)
854
- }
855
- if (kw === 'class') {
856
- const classDecl = this.parseClassDeclaration()
857
- classDecl.declare = true
858
- return classDecl
859
- }
860
- if (kw === 'const' || kw === 'let' || kw === 'var') {
861
- const varDecl = this.parseVariableDeclaration()
862
- varDecl.declare = true
863
- return varDecl
864
- }
865
- if (kw === 'interface') {
866
- const ifaceDecl = this.parseInterfaceDeclaration()
867
- ifaceDecl.declare = true
868
- return ifaceDecl
869
- }
870
- if (kw === 'type') {
871
- const typeDecl = this.parseTypeAliasDeclaration()
872
- typeDecl.declare = true
873
- return typeDecl
874
- }
875
- if (kw === 'enum') {
876
- const enumDecl = this.parseEnumDeclaration()
877
- enumDecl.declare = true
878
- return enumDecl
879
- }
880
- if (kw === 'namespace' || kw === 'module') {
881
- const nsDecl = this.parseNamespaceDeclaration()
882
- nsDecl.declare = true
883
- return nsDecl
884
- }
885
- if (kw === 'global') {
886
- this.advance()
887
- this.expect('LBRACE')
888
- const body = []
889
- while (!this.match('RBRACE', 'EOF')) {
890
- body.push(this.parseStatement())
891
- }
892
- this.expect('RBRACE')
893
- return new AST.TSModuleDeclaration(null, new AST.TSModuleBlock(body), true, true, loc)
894
- }
895
- }
896
-
897
- throw new Error(`Déclaration inattendue après declare à ligne ${loc.line}`)
898
- }
899
-
900
- parseDeclareFunction(loc) {
901
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
902
-
903
- let typeParameters = null
904
- if (this.match('LT')) {
905
- typeParameters = this.parseTypeParameters()
906
- }
907
-
908
- this.expect('LPAREN')
909
- const params = this.parseParameterList()
910
- this.expect('RPAREN')
911
-
912
- let returnType = null
913
- if (this.match('COLON')) {
914
- this.advance()
915
- returnType = new AST.TSTypeAnnotation(this.parseType())
916
- }
917
-
918
- if (this.match('SEMICOLON')) this.advance()
919
-
920
- return new AST.TSDeclareFunction(id, params, returnType, typeParameters, false, false, loc)
921
- }
922
-
923
- parseClassDeclaration() {
924
- const loc = this.peek().loc
925
- const decorators = []
926
- let abstract = false
927
-
928
- while (this.match('AT')) {
929
- decorators.push(this.parseDecorator())
930
- }
931
-
932
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'abstract') {
933
- abstract = true
934
- this.advance()
935
- }
936
-
937
- this.expect('KEYWORD')
938
-
939
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
940
-
941
- let typeParameters = null
942
- if (this.match('LT')) {
943
- typeParameters = this.parseTypeParameters()
944
- }
945
-
946
- let superClass = null
947
- let superTypeParameters = null
948
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'extends') {
949
- this.advance()
950
- superClass = this.parseIdentifierOrQualifiedName()
951
- if (this.match('LT')) {
952
- superTypeParameters = this.parseTypeArguments()
953
- }
954
- }
955
-
956
- const implements_ = []
957
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'implements') {
958
- this.advance()
959
- implements_.push(this.parseInterfaceHeritage())
960
- while (this.match('COMMA')) {
961
- this.advance()
962
- implements_.push(this.parseInterfaceHeritage())
963
- }
964
- }
965
-
966
- const body = this.parseClassBody()
967
-
968
- return new AST.ClassDeclaration(id, body, superClass, implements_, decorators, abstract, typeParameters, superTypeParameters, loc)
969
- }
970
-
971
- parseAbstractClass() {
972
- this.advance()
973
- return this.parseClassDeclaration()
974
- }
975
-
976
- parseClassBody() {
977
- this.expect('LBRACE')
978
- const body = []
979
-
980
- while (!this.match('RBRACE', 'EOF')) {
981
- const member = this.parseClassMember()
982
- if (member) body.push(member)
983
- }
984
-
985
- this.expect('RBRACE')
986
- return new AST.ClassBody(body)
987
- }
988
-
989
- parseClassMember() {
990
- const loc = this.peek().loc
991
- const decorators = []
992
-
993
- while (this.match('AT')) {
994
- decorators.push(this.parseDecorator())
995
- }
996
-
997
- let accessibility = null
998
- let isStatic = false
999
- let readonly = false
1000
- let abstract = false
1001
- let override = false
1002
-
1003
- while (this.match('KEYWORD')) {
1004
- const kw = this.translateKeyword(this.peek().value)
1005
- if (kw === 'public' || kw === 'private' || kw === 'protected') {
1006
- accessibility = kw
1007
- this.advance()
1008
- } else if (kw === 'static') {
1009
- isStatic = true
1010
- this.advance()
1011
- } else if (kw === 'readonly') {
1012
- readonly = true
1013
- this.advance()
1014
- } else if (kw === 'abstract') {
1015
- abstract = true
1016
- this.advance()
1017
- } else if (kw === 'override') {
1018
- override = true
1019
- this.advance()
1020
- } else {
1021
- break
1022
- }
1023
- }
1024
-
1025
- if (isStatic && this.match('LBRACE')) {
1026
- return this.parseStaticBlock()
1027
- }
1028
-
1029
- if (this.match('KEYWORD')) {
1030
- const kw = this.translateKeyword(this.peek().value)
1031
-
1032
- if (kw === 'constructor') {
1033
- this.advance()
1034
- return this.parseConstructor(accessibility, loc)
1035
- }
1036
-
1037
- if (kw === 'get' || kw === 'set') {
1038
- const kind = kw
1039
- this.advance()
1040
- return this.parseAccessor(kind, accessibility, isStatic, decorators, loc)
1041
- }
1042
- }
1043
-
1044
- const key = this.parsePropertyName()
1045
-
1046
- let optional = false
1047
- let definite = false
1048
-
1049
- if (this.match('QUESTION')) {
1050
- optional = true
1051
- this.advance()
1052
- } else if (this.match('NOT')) {
1053
- definite = true
1054
- this.advance()
1055
- }
1056
-
1057
- if (this.match('LPAREN') || this.match('LT')) {
1058
- return this.parseMethod(key, accessibility, isStatic, abstract, override, decorators, loc)
1059
- }
1060
-
1061
- return this.parseProperty(key, accessibility, isStatic, readonly, abstract, override, optional, definite, decorators, loc)
1062
- }
1063
-
1064
- parseConstructor(accessibility, loc) {
1065
- this.expect('LPAREN')
1066
- const params = this.parseConstructorParameters()
1067
- this.expect('RPAREN')
1068
-
1069
- let body = null
1070
- if (this.match('LBRACE')) {
1071
- body = this.parseBlockStatement()
1072
- }
1073
-
1074
- return new AST.MethodDefinition(
1075
- new AST.Identifier('constructor'),
1076
- new AST.FunctionExpression(null, params, body),
1077
- 'constructor',
1078
- false,
1079
- false,
1080
- accessibility,
1081
- false,
1082
- false,
1083
- [],
1084
- loc
1085
- )
1086
- }
1087
-
1088
- parseConstructorParameters() {
1089
- const params = []
1090
-
1091
- while (!this.match('RPAREN', 'EOF')) {
1092
- let accessibility = null
1093
- let readonly = false
1094
- let override = false
1095
-
1096
- while (this.match('KEYWORD')) {
1097
- const kw = this.translateKeyword(this.peek().value)
1098
- if (kw === 'public' || kw === 'private' || kw === 'protected') {
1099
- accessibility = kw
1100
- this.advance()
1101
- } else if (kw === 'readonly') {
1102
- readonly = true
1103
- this.advance()
1104
- } else if (kw === 'override') {
1105
- override = true
1106
- this.advance()
1107
- } else {
1108
- break
1109
- }
1110
- }
1111
-
1112
- const param = this.parseParameter()
1113
-
1114
- if (accessibility || readonly || override) {
1115
- params.push(new AST.TSParameterProperty(param, accessibility, readonly, override))
1116
- } else {
1117
- params.push(param)
1118
- }
1119
-
1120
- if (!this.match('RPAREN')) {
1121
- this.expect('COMMA')
1122
- }
1123
- }
1124
-
1125
- return params
1126
- }
1127
-
1128
- parseMethod(key, accessibility, isStatic, abstract, override, decorators, loc) {
1129
- let typeParameters = null
1130
- if (this.match('LT')) {
1131
- typeParameters = this.parseTypeParameters()
1132
- }
1133
-
1134
- this.expect('LPAREN')
1135
- const params = this.parseParameterList()
1136
- this.expect('RPAREN')
1137
-
1138
- let returnType = null
1139
- if (this.match('COLON')) {
1140
- this.advance()
1141
- returnType = new AST.TSTypeAnnotation(this.parseType())
1142
- }
1143
-
1144
- let body = null
1145
- if (this.match('LBRACE')) {
1146
- body = this.parseBlockStatement()
1147
- } else if (this.match('SEMICOLON')) {
1148
- this.advance()
1149
- }
1150
-
1151
- return new AST.MethodDefinition(
1152
- key,
1153
- new AST.FunctionExpression(null, params, body, false, false, returnType, typeParameters),
1154
- 'method',
1155
- key.type === 'Identifier' ? false : true,
1156
- isStatic,
1157
- accessibility,
1158
- abstract,
1159
- override,
1160
- decorators,
1161
- loc
1162
- )
1163
- }
1164
-
1165
- parseAccessor(kind, accessibility, isStatic, decorators, loc) {
1166
- const key = this.parsePropertyName()
1167
-
1168
- this.expect('LPAREN')
1169
- const params = this.parseParameterList()
1170
- this.expect('RPAREN')
1171
-
1172
- let returnType = null
1173
- if (this.match('COLON')) {
1174
- this.advance()
1175
- returnType = new AST.TSTypeAnnotation(this.parseType())
1176
- }
1177
-
1178
- let body = null
1179
- if (this.match('LBRACE')) {
1180
- body = this.parseBlockStatement()
1181
- }
1182
-
1183
- return new AST.MethodDefinition(
1184
- key,
1185
- new AST.FunctionExpression(null, params, body, false, false, returnType),
1186
- kind,
1187
- false,
1188
- isStatic,
1189
- accessibility,
1190
- false,
1191
- false,
1192
- decorators,
1193
- loc
1194
- )
1195
- }
1196
-
1197
- parseProperty(key, accessibility, isStatic, readonly, abstract, override, optional, definite, decorators, loc) {
1198
- let typeAnnotation = null
1199
- if (this.match('COLON')) {
1200
- this.advance()
1201
- typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
1202
- }
1203
-
1204
- let value = null
1205
- if (this.match('ASSIGN')) {
1206
- this.advance()
1207
- value = this.parseExpression()
1208
- }
1209
-
1210
- if (this.match('SEMICOLON')) this.advance()
1211
-
1212
- return new AST.PropertyDefinition(
1213
- key, value, false, isStatic, accessibility, readonly, abstract, override, optional, definite, typeAnnotation, decorators, loc
1214
- )
1215
- }
1216
-
1217
- parseStaticBlock() {
1218
- this.expect('LBRACE')
1219
- const body = []
1220
-
1221
- while (!this.match('RBRACE', 'EOF')) {
1222
- body.push(this.parseStatement())
1223
- }
1224
-
1225
- this.expect('RBRACE')
1226
- return new AST.StaticBlock(body)
1227
- }
1228
-
1229
- parseDecorator() {
1230
- const loc = this.peek().loc
1231
- this.expect('AT')
1232
-
1233
- let expression = this.parseIdentifierOrQualifiedName()
1234
-
1235
- if (this.match('LPAREN')) {
1236
- this.advance()
1237
- const args = []
1238
- while (!this.match('RPAREN', 'EOF')) {
1239
- args.push(this.parseExpression())
1240
- if (!this.match('RPAREN')) {
1241
- this.expect('COMMA')
1242
- }
1243
- }
1244
- this.expect('RPAREN')
1245
- expression = new AST.CallExpression(expression, args, false, loc)
1246
- }
1247
-
1248
- return new AST.Decorator(expression, loc)
1249
- }
1250
-
1251
- parseDecoratedDeclaration() {
1252
- const decorators = []
1253
- while (this.match('AT')) {
1254
- decorators.push(this.parseDecorator())
1255
- }
1256
-
1257
- const declaration = this.parseStatement()
1258
- if (declaration.decorators !== undefined) {
1259
- declaration.decorators = decorators.concat(declaration.decorators)
1260
- }
1261
- return declaration
1262
- }
1263
-
1264
- parseFunctionDeclaration() {
1265
- const loc = this.peek().loc
1266
- let async = false
1267
-
1268
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'async') {
1269
- async = true
1270
- this.advance()
1271
- }
1272
-
1273
- this.advance()
1274
-
1275
- let generator = false
1276
- if (this.match('TIMES')) {
1277
- generator = true
1278
- this.advance()
1279
- }
1280
-
1281
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
1282
-
1283
- let typeParameters = null
1284
- if (this.match('LT')) {
1285
- typeParameters = this.parseTypeParameters()
1286
- }
1287
-
1288
- this.expect('LPAREN')
1289
- const params = this.parseParameterList()
1290
- this.expect('RPAREN')
1291
-
1292
- let returnType = null
1293
- if (this.match('COLON')) {
1294
- this.advance()
1295
- returnType = new AST.TSTypeAnnotation(this.parseType())
1296
- }
1297
-
1298
- const body = this.parseBlockStatement()
1299
-
1300
- return new AST.FunctionDeclaration(id, params, body, async, generator, returnType, typeParameters, loc)
1301
- }
1302
-
1303
- parseAsyncFunction() {
1304
- this.advance()
1305
- return this.parseFunctionDeclaration()
1306
- }
1307
-
1308
- parseVariableDeclaration() {
1309
- const loc = this.peek().loc
1310
- const kind = this.translateKeyword(this.advance().value)
1311
- const declarations = []
1312
-
1313
- do {
1314
- if (this.match('COMMA')) this.advance()
1315
- declarations.push(this.parseVariableDeclarator())
1316
- } while (this.match('COMMA'))
1317
-
1318
- if (this.match('SEMICOLON')) this.advance()
1319
-
1320
- return new AST.VariableDeclaration(kind, declarations, loc)
1321
- }
1322
-
1323
- parseVariableDeclarator() {
1324
- const loc = this.peek().loc
1325
- const id = this.parseBindingPattern()
1326
-
1327
- let init = null
1328
- if (this.match('ASSIGN')) {
1329
- this.advance()
1330
- init = this.parseExpression()
1331
- }
1332
-
1333
- return new AST.VariableDeclarator(id, init, loc)
1334
- }
1335
-
1336
- parseBindingPattern() {
1337
- if (this.match('LBRACKET')) {
1338
- return this.parseArrayPattern()
1339
- }
1340
- if (this.match('LBRACE')) {
1341
- return this.parseObjectPattern()
1342
- }
1343
-
1344
- const id = new AST.Identifier(this.expect('IDENTIFIER').value)
1345
-
1346
- if (this.match('COLON')) {
1347
- this.advance()
1348
- id.typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
1349
- }
1350
-
1351
- return id
1352
- }
1353
-
1354
- parseArrayPattern() {
1355
- const loc = this.peek().loc
1356
- this.expect('LBRACKET')
1357
- const elements = []
1358
-
1359
- while (!this.match('RBRACKET', 'EOF')) {
1360
- if (this.match('COMMA')) {
1361
- elements.push(null)
1362
- this.advance()
1363
- continue
1364
- }
1365
-
1366
- if (this.match('SPREAD')) {
1367
- this.advance()
1368
- const argument = this.parseBindingPattern()
1369
- elements.push(new AST.RestElement(argument))
1370
- break
1371
- }
1372
-
1373
- elements.push(this.parseBindingPattern())
1374
-
1375
- if (!this.match('RBRACKET')) {
1376
- this.expect('COMMA')
1377
- }
1378
- }
1379
-
1380
- this.expect('RBRACKET')
1381
-
1382
- let typeAnnotation = null
1383
- if (this.match('COLON')) {
1384
- this.advance()
1385
- typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
1386
- }
1387
-
1388
- return new AST.ArrayPattern(elements, typeAnnotation, loc)
1389
- }
1390
-
1391
- parseObjectPattern() {
1392
- const loc = this.peek().loc
1393
- this.expect('LBRACE')
1394
- const properties = []
1395
-
1396
- while (!this.match('RBRACE', 'EOF')) {
1397
- if (this.match('SPREAD')) {
1398
- this.advance()
1399
- const argument = this.parseBindingPattern()
1400
- properties.push(new AST.RestElement(argument))
1401
- break
1402
- }
1403
-
1404
- const key = this.parsePropertyName()
1405
- let value = key
1406
- let shorthand = true
1407
-
1408
- if (this.match('COLON')) {
1409
- this.advance()
1410
- value = this.parseBindingPattern()
1411
- shorthand = false
1412
- }
1413
-
1414
- if (this.match('ASSIGN')) {
1415
- this.advance()
1416
- const defaultValue = this.parseExpression()
1417
- value = new AST.AssignmentPattern(value, defaultValue)
1418
- }
1419
-
1420
- properties.push(new AST.Property(key, value, 'init', false, shorthand, false))
1421
-
1422
- if (!this.match('RBRACE')) {
1423
- this.expect('COMMA')
1424
- }
1425
- }
1426
-
1427
- this.expect('RBRACE')
1428
-
1429
- let typeAnnotation = null
1430
- if (this.match('COLON')) {
1431
- this.advance()
1432
- typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
1433
- }
1434
-
1435
- return new AST.ObjectPattern(properties, typeAnnotation, loc)
1436
- }
1437
-
1438
- parseParameterList() {
1439
- const params = []
1440
-
1441
- while (!this.match('RPAREN', 'EOF')) {
1442
- params.push(this.parseParameter())
1443
- if (!this.match('RPAREN')) {
1444
- this.expect('COMMA')
1445
- }
1446
- }
1447
-
1448
- return params
1449
- }
1450
-
1451
- parseParameter() {
1452
- const loc = this.peek().loc
1453
- let rest = false
1454
-
1455
- if (this.match('SPREAD')) {
1456
- this.advance()
1457
- rest = true
1458
- }
1459
-
1460
- const pattern = this.parseBindingPattern()
1461
-
1462
- let optional = false
1463
- if (this.match('QUESTION')) {
1464
- optional = true
1465
- this.advance()
1466
- }
1467
-
1468
- if (this.match('COLON') && !pattern.typeAnnotation) {
1469
- this.advance()
1470
- pattern.typeAnnotation = new AST.TSTypeAnnotation(this.parseType())
1471
- }
1472
-
1473
- if (optional) {
1474
- pattern.optional = true
1475
- }
1476
-
1477
- let defaultValue = null
1478
- if (this.match('ASSIGN')) {
1479
- this.advance()
1480
- defaultValue = this.parseExpression()
1481
- }
1482
-
1483
- if (rest) {
1484
- return new AST.RestElement(pattern, pattern.typeAnnotation, loc)
1485
- }
1486
-
1487
- if (defaultValue) {
1488
- return new AST.AssignmentPattern(pattern, defaultValue, loc)
1489
- }
1490
-
1491
- return pattern
1492
- }
1493
-
1494
- parseTypeParameters() {
1495
- this.expect('LT')
1496
- const params = []
1497
-
1498
- while (!this.match('GT', 'EOF')) {
1499
- params.push(this.parseTypeParameter())
1500
- if (!this.match('GT')) {
1501
- this.expect('COMMA')
1502
- }
1503
- }
1504
-
1505
- this.expect('GT')
1506
- return new AST.TSTypeParameterDeclaration(params)
1507
- }
1508
-
1509
- parseTypeParameter() {
1510
- const loc = this.peek().loc
1511
- let in_ = false
1512
- let out = false
1513
- let const_ = false
1514
-
1515
- while (this.match('KEYWORD')) {
1516
- const kw = this.translateKeyword(this.peek().value)
1517
- if (kw === 'in') { in_ = true; this.advance() }
1518
- else if (kw === 'out') { out = true; this.advance() }
1519
- else if (kw === 'const') { const_ = true; this.advance() }
1520
- else break
1521
- }
1522
-
1523
- const name = new AST.Identifier(this.expect('IDENTIFIER').value)
1524
-
1525
- let constraint = null
1526
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'extends') {
1527
- this.advance()
1528
- constraint = this.parseType()
1529
- }
1530
-
1531
- let default_ = null
1532
- if (this.match('ASSIGN')) {
1533
- this.advance()
1534
- default_ = this.parseType()
1535
- }
1536
-
1537
- return new AST.TSTypeParameter(name, constraint, default_, in_, out, const_, loc)
1538
- }
1539
-
1540
- parseTypeArguments() {
1541
- this.expect('LT')
1542
- const params = []
1543
-
1544
- while (!this.match('GT', 'EOF')) {
1545
- params.push(this.parseType())
1546
- if (!this.match('GT')) {
1547
- this.expect('COMMA')
1548
- }
1549
- }
1550
-
1551
- this.expect('GT')
1552
- return new AST.TSTypeParameterInstantiation(params)
1553
- }
1554
-
1555
- parseType() {
1556
- return this.parseUnionType()
1557
- }
1558
-
1559
- parseUnionType() {
1560
- if (this.match('BIT_OR')) this.advance()
1561
-
1562
- let type = this.parseIntersectionType()
1563
-
1564
- if (this.match('BIT_OR')) {
1565
- const types = [type]
1566
- while (this.match('BIT_OR')) {
1567
- this.advance()
1568
- types.push(this.parseIntersectionType())
1569
- }
1570
- return new AST.TSUnionType(types)
1571
- }
1572
-
1573
- return type
1574
- }
1575
-
1576
- parseIntersectionType() {
1577
- if (this.match('BIT_AND')) this.advance()
1578
-
1579
- let type = this.parseTypeOperator()
1580
-
1581
- if (this.match('BIT_AND')) {
1582
- const types = [type]
1583
- while (this.match('BIT_AND')) {
1584
- this.advance()
1585
- types.push(this.parseTypeOperator())
1586
- }
1587
- return new AST.TSIntersectionType(types)
1588
- }
1589
-
1590
- return type
1591
- }
1592
-
1593
- parseTypeOperator() {
1594
- if (this.match('KEYWORD')) {
1595
- const kw = this.translateKeyword(this.peek().value)
1596
-
1597
- if (kw === 'keyof') {
1598
- this.advance()
1599
- return new AST.TSTypeOperator('keyof', this.parseTypeOperator())
1600
- }
1601
- if (kw === 'typeof') {
1602
- this.advance()
1603
- const exprName = this.parseIdentifierOrQualifiedName()
1604
- let typeParameters = null
1605
- if (this.match('LT')) {
1606
- typeParameters = this.parseTypeArguments()
1607
- }
1608
- return new AST.TSTypeQuery(exprName, typeParameters)
1609
- }
1610
- if (kw === 'readonly') {
1611
- this.advance()
1612
- return new AST.TSTypeOperator('readonly', this.parseTypeOperator())
1613
- }
1614
- if (kw === 'infer') {
1615
- this.advance()
1616
- const param = this.parseTypeParameter()
1617
- return new AST.TSInferType(param)
1618
- }
1619
- }
1620
-
1621
- return this.parseArrayPostfix()
1622
- }
1623
-
1624
- parseArrayPostfix() {
1625
- let type = this.parsePrimaryType()
1626
-
1627
- while (true) {
1628
- if (this.match('LBRACKET')) {
1629
- this.advance()
1630
- if (this.match('RBRACKET')) {
1631
- this.advance()
1632
- type = new AST.TSArrayType(type)
1633
- } else {
1634
- const indexType = this.parseType()
1635
- this.expect('RBRACKET')
1636
- type = new AST.TSIndexedAccessType(type, indexType)
1637
- }
1638
- } else {
1639
- break
1640
- }
1641
- }
1642
-
1643
- return type
1644
- }
1645
-
1646
- parsePrimaryType() {
1647
- const loc = this.peek().loc
1648
-
1649
- if (this.match('TYPE')) {
1650
- const typeName = this.translateType(this.advance().value)
1651
-
1652
- switch (typeName) {
1653
- case 'string': return new AST.TSStringKeyword(loc)
1654
- case 'number': return new AST.TSNumberKeyword(loc)
1655
- case 'boolean': return new AST.TSBooleanKeyword(loc)
1656
- case 'bigint': return new AST.TSBigIntKeyword(loc)
1657
- case 'symbol': return new AST.TSSymbolKeyword(loc)
1658
- case 'object': return new AST.TSObjectKeyword(loc)
1659
- case 'any': return new AST.TSAnyKeyword(loc)
1660
- case 'unknown': return new AST.TSUnknownKeyword(loc)
1661
- case 'never': return new AST.TSNeverKeyword(loc)
1662
- case 'void': return new AST.TSVoidKeyword(loc)
1663
- }
1664
-
1665
- let typeParameters = null
1666
- if (this.match('LT')) {
1667
- typeParameters = this.parseTypeArguments()
1668
- }
1669
- return new AST.TSTypeReference(new AST.Identifier(typeName), typeParameters, loc)
1670
- }
1671
-
1672
- if (this.match('KEYWORD')) {
1673
- const kw = this.translateKeyword(this.peek().value)
1674
-
1675
- if (kw === 'undefined') {
1676
- this.advance()
1677
- return new AST.TSUndefinedKeyword(loc)
1678
- }
1679
- if (kw === 'null') {
1680
- this.advance()
1681
- return new AST.TSNullKeyword(loc)
1682
- }
1683
- if (kw === 'this') {
1684
- this.advance()
1685
- return new AST.TSThisType(loc)
1686
- }
1687
- if (kw === 'true' || kw === 'false') {
1688
- this.advance()
1689
- return new AST.TSLiteralType(new AST.BooleanLiteral(kw === 'true'))
1690
- }
1691
- if (kw === 'new') {
1692
- return this.parseConstructorType()
1693
- }
1694
- }
1695
-
1696
- if (this.match('IDENTIFIER')) {
1697
- const name = this.parseIdentifierOrQualifiedName()
1698
- let typeParameters = null
1699
- if (this.match('LT')) {
1700
- typeParameters = this.parseTypeArguments()
1701
- }
1702
- return new AST.TSTypeReference(name, typeParameters, loc)
1703
- }
1704
-
1705
- if (this.match('STRING')) {
1706
- const token = this.advance()
1707
- return new AST.TSLiteralType(new AST.StringLiteral(token.value, token.raw))
1708
- }
1709
-
1710
- if (this.match('NUMBER')) {
1711
- const token = this.advance()
1712
- return new AST.TSLiteralType(new AST.NumericLiteral(token.value, token.raw))
1713
- }
1714
-
1715
- if (this.match('MINUS') && this.peek(1).type === 'NUMBER') {
1716
- this.advance()
1717
- const token = this.advance()
1718
- return new AST.TSLiteralType(new AST.NumericLiteral(-token.value, '-' + token.raw))
1719
- }
1720
-
1721
- if (this.match('LBRACE')) {
1722
- return this.parseTypeLiteral()
1723
- }
1724
-
1725
- if (this.match('LBRACKET')) {
1726
- return this.parseTupleType()
1727
- }
1728
-
1729
- if (this.match('LPAREN')) {
1730
- this.advance()
1731
- const type = this.parseType()
1732
- this.expect('RPAREN')
1733
-
1734
- if (this.match('ARROW')) {
1735
- this.advance()
1736
- const returnType = this.parseType()
1737
- return new AST.TSFunctionType([type], new AST.TSTypeAnnotation(returnType))
1738
- }
1739
-
1740
- return new AST.TSParenthesizedType(type)
1741
- }
1742
-
1743
- throw new Error(`Type inattendu à ligne ${loc.line}`)
1744
- }
1745
-
1746
- parseTypeLiteral() {
1747
- this.expect('LBRACE')
1748
- const members = []
1749
-
1750
- while (!this.match('RBRACE', 'EOF')) {
1751
- const member = this.parseTypeMember()
1752
- if (member) members.push(member)
1753
- if (this.match('SEMICOLON', 'COMMA')) this.advance()
1754
- }
1755
-
1756
- this.expect('RBRACE')
1757
- return new AST.TSTypeLiteral(members)
1758
- }
1759
-
1760
- parseTupleType() {
1761
- this.expect('LBRACKET')
1762
- const elementTypes = []
1763
-
1764
- while (!this.match('RBRACKET', 'EOF')) {
1765
- if (this.match('SPREAD')) {
1766
- this.advance()
1767
- elementTypes.push(new AST.TSRestType(this.parseType()))
1768
- } else {
1769
- let label = null
1770
- let optional = false
1771
-
1772
- if (this.match('IDENTIFIER') && this.peek(1).type === 'COLON') {
1773
- label = new AST.Identifier(this.advance().value)
1774
- this.advance()
1775
- }
1776
-
1777
- const type = this.parseType()
1778
-
1779
- if (this.match('QUESTION')) {
1780
- optional = true
1781
- this.advance()
1782
- }
1783
-
1784
- if (label) {
1785
- elementTypes.push(new AST.TSNamedTupleMember(label, type, optional))
1786
- } else if (optional) {
1787
- elementTypes.push(new AST.TSOptionalType(type))
1788
- } else {
1789
- elementTypes.push(type)
1790
- }
1791
- }
1792
-
1793
- if (!this.match('RBRACKET')) {
1794
- this.expect('COMMA')
1795
- }
1796
- }
1797
-
1798
- this.expect('RBRACKET')
1799
- return new AST.TSTupleType(elementTypes)
1800
- }
1801
-
1802
- parseConstructorType() {
1803
- const loc = this.peek().loc
1804
- let abstract = false
1805
-
1806
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'abstract') {
1807
- abstract = true
1808
- this.advance()
1809
- }
1810
-
1811
- this.advance()
1812
-
1813
- let typeParameters = null
1814
- if (this.match('LT')) {
1815
- typeParameters = this.parseTypeParameters()
1816
- }
1817
-
1818
- this.expect('LPAREN')
1819
- const params = this.parseParameterList()
1820
- this.expect('RPAREN')
1821
-
1822
- this.expect('ARROW')
1823
- const returnType = this.parseType()
1824
-
1825
- return new AST.TSConstructorType(params, new AST.TSTypeAnnotation(returnType), typeParameters, abstract, loc)
1826
- }
1827
-
1828
- parseIdentifierOrQualifiedName() {
1829
- let left = new AST.Identifier(this.expect('IDENTIFIER').value)
1830
-
1831
- while (this.match('DOT')) {
1832
- this.advance()
1833
- const right = new AST.Identifier(this.expect('IDENTIFIER').value)
1834
- left = new AST.TSQualifiedName(left, right)
1835
- }
1836
-
1837
- return left
1838
- }
1839
-
1840
- parsePropertyName() {
1841
- if (this.match('STRING')) {
1842
- const token = this.advance()
1843
- return new AST.StringLiteral(token.value, token.raw)
1844
- }
1845
- if (this.match('NUMBER')) {
1846
- const token = this.advance()
1847
- return new AST.NumericLiteral(token.value, token.raw)
1848
- }
1849
- if (this.match('LBRACKET')) {
1850
- this.advance()
1851
- const expr = this.parseExpression()
1852
- this.expect('RBRACKET')
1853
- return expr
1854
- }
1855
- if (this.match('PRIVATE_IDENTIFIER')) {
1856
- return new AST.PrivateIdentifier(this.advance().value)
1857
- }
1858
-
1859
- return new AST.Identifier(this.expect('IDENTIFIER').value)
1860
- }
1861
-
1862
- parseIfStatement() {
1863
- const loc = this.peek().loc
1864
- this.advance()
1865
-
1866
- this.expect('LPAREN')
1867
- const test = this.parseExpression()
1868
- this.expect('RPAREN')
1869
-
1870
- const consequent = this.parseStatement()
1871
-
1872
- let alternate = null
1873
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'else') {
1874
- this.advance()
1875
- alternate = this.parseStatement()
1876
- }
1877
-
1878
- return new AST.IfStatement(test, consequent, alternate, loc)
1879
- }
1880
-
1881
- parseSwitchStatement() {
1882
- const loc = this.peek().loc
1883
- this.advance()
1884
-
1885
- this.expect('LPAREN')
1886
- const discriminant = this.parseExpression()
1887
- this.expect('RPAREN')
1888
-
1889
- this.expect('LBRACE')
1890
- const cases = []
1891
-
1892
- while (!this.match('RBRACE', 'EOF')) {
1893
- cases.push(this.parseSwitchCase())
1894
- }
1895
-
1896
- this.expect('RBRACE')
1897
- return new AST.SwitchStatement(discriminant, cases, loc)
1898
- }
1899
-
1900
- parseSwitchCase() {
1901
- const loc = this.peek().loc
1902
- let test = null
1903
-
1904
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'case') {
1905
- this.advance()
1906
- test = this.parseExpression()
1907
- } else {
1908
- this.advance()
1909
- }
1910
-
1911
- this.expect('COLON')
1912
-
1913
- const consequent = []
1914
- while (!this.match('RBRACE', 'EOF')) {
1915
- const next = this.peek()
1916
- if (next.type === 'KEYWORD') {
1917
- const kw = this.translateKeyword(next.value)
1918
- if (kw === 'case' || kw === 'default') break
1919
- }
1920
- consequent.push(this.parseStatement())
1921
- }
1922
-
1923
- return new AST.SwitchCase(test, consequent, loc)
1924
- }
1925
-
1926
- parseForStatement() {
1927
- const loc = this.peek().loc
1928
- this.advance()
1929
-
1930
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'await') {
1931
- this.advance()
1932
- return this.parseForAwaitOf(loc)
1933
- }
1934
-
1935
- this.expect('LPAREN')
1936
-
1937
- let init = null
1938
- if (!this.match('SEMICOLON')) {
1939
- if (this.match('KEYWORD')) {
1940
- const kw = this.translateKeyword(this.peek().value)
1941
- if (kw === 'const' || kw === 'let' || kw === 'var') {
1942
- init = this.parseVariableDeclaration()
1943
-
1944
- if (this.peek(-1).type !== 'SEMICOLON') {
1945
- if (this.match('KEYWORD')) {
1946
- const nextKw = this.translateKeyword(this.peek().value)
1947
- if (nextKw === 'in') {
1948
- return this.parseForIn(init, loc)
1949
- }
1950
- if (nextKw === 'of') {
1951
- return this.parseForOf(init, loc, false)
1952
- }
1953
- }
1954
- }
1955
- } else {
1956
- init = this.parseExpression()
1957
- }
1958
- } else {
1959
- init = this.parseExpression()
1960
- }
1961
- }
1962
-
1963
- if (!this.match('SEMICOLON')) {
1964
- if (this.match('KEYWORD')) {
1965
- const kw = this.translateKeyword(this.peek().value)
1966
- if (kw === 'in') return this.parseForIn(init, loc)
1967
- if (kw === 'of') return this.parseForOf(init, loc, false)
1968
- }
1969
- }
1970
-
1971
- this.expect('SEMICOLON')
1972
-
1973
- const test = this.match('SEMICOLON') ? null : this.parseExpression()
1974
- this.expect('SEMICOLON')
1975
-
1976
- const update = this.match('RPAREN') ? null : this.parseExpression()
1977
- this.expect('RPAREN')
1978
-
1979
- const body = this.parseStatement()
1980
-
1981
- return new AST.ForStatement(init, test, update, body, loc)
1982
- }
1983
-
1984
- parseForIn(left, loc) {
1985
- this.advance()
1986
- const right = this.parseExpression()
1987
- this.expect('RPAREN')
1988
- const body = this.parseStatement()
1989
- return new AST.ForInStatement(left, right, body, loc)
1990
- }
1991
-
1992
- parseForOf(left, loc, await_) {
1993
- this.advance()
1994
- const right = this.parseExpression()
1995
- this.expect('RPAREN')
1996
- const body = this.parseStatement()
1997
- return new AST.ForOfStatement(left, right, body, await_, loc)
1998
- }
1999
-
2000
- parseForAwaitOf(loc) {
2001
- this.expect('LPAREN')
2002
-
2003
- let left
2004
- if (this.match('KEYWORD')) {
2005
- const kw = this.translateKeyword(this.peek().value)
2006
- if (kw === 'const' || kw === 'let' || kw === 'var') {
2007
- left = this.parseVariableDeclaration()
2008
- }
2009
- }
2010
- if (!left) {
2011
- left = this.parseExpression()
2012
- }
2013
-
2014
- this.expect('KEYWORD')
2015
- return this.parseForOf(left, loc, true)
2016
- }
2017
-
2018
- parseWhileStatement() {
2019
- const loc = this.peek().loc
2020
- this.advance()
2021
-
2022
- this.expect('LPAREN')
2023
- const test = this.parseExpression()
2024
- this.expect('RPAREN')
2025
-
2026
- const body = this.parseStatement()
2027
-
2028
- return new AST.WhileStatement(test, body, loc)
2029
- }
2030
-
2031
- parseDoWhileStatement() {
2032
- const loc = this.peek().loc
2033
- this.advance()
2034
-
2035
- const body = this.parseStatement()
2036
-
2037
- this.expect('KEYWORD')
2038
- this.expect('LPAREN')
2039
- const test = this.parseExpression()
2040
- this.expect('RPAREN')
2041
-
2042
- if (this.match('SEMICOLON')) this.advance()
2043
-
2044
- return new AST.DoWhileStatement(body, test, loc)
2045
- }
2046
-
2047
- parseTryStatement() {
2048
- const loc = this.peek().loc
2049
- this.advance()
2050
-
2051
- const block = this.parseBlockStatement()
2052
-
2053
- let handler = null
2054
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'catch') {
2055
- handler = this.parseCatchClause()
2056
- }
2057
-
2058
- let finalizer = null
2059
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'finally') {
2060
- this.advance()
2061
- finalizer = this.parseBlockStatement()
2062
- }
2063
-
2064
- return new AST.TryStatement(block, handler, finalizer, loc)
2065
- }
2066
-
2067
- parseCatchClause() {
2068
- const loc = this.peek().loc
2069
- this.advance()
2070
-
2071
- let param = null
2072
- if (this.match('LPAREN')) {
2073
- this.advance()
2074
- param = this.parseBindingPattern()
2075
- this.expect('RPAREN')
2076
- }
2077
-
2078
- const body = this.parseBlockStatement()
2079
-
2080
- return new AST.CatchClause(param, body, loc)
2081
- }
2082
-
2083
- parseThrowStatement() {
2084
- const loc = this.peek().loc
2085
- this.advance()
2086
-
2087
- const argument = this.parseExpression()
2088
- if (this.match('SEMICOLON')) this.advance()
2089
-
2090
- return new AST.ThrowStatement(argument, loc)
2091
- }
2092
-
2093
- parseReturnStatement() {
2094
- const loc = this.peek().loc
2095
- this.advance()
2096
-
2097
- let argument = null
2098
- if (!this.match('SEMICOLON', 'RBRACE', 'EOF')) {
2099
- argument = this.parseExpression()
2100
- }
2101
-
2102
- if (this.match('SEMICOLON')) this.advance()
2103
-
2104
- return new AST.ReturnStatement(argument, loc)
2105
- }
2106
-
2107
- parseBreakStatement() {
2108
- const loc = this.peek().loc
2109
- this.advance()
2110
-
2111
- let label = null
2112
- if (this.match('IDENTIFIER')) {
2113
- label = new AST.Identifier(this.advance().value)
2114
- }
2115
-
2116
- if (this.match('SEMICOLON')) this.advance()
2117
-
2118
- return new AST.BreakStatement(label, loc)
2119
- }
2120
-
2121
- parseContinueStatement() {
2122
- const loc = this.peek().loc
2123
- this.advance()
2124
-
2125
- let label = null
2126
- if (this.match('IDENTIFIER')) {
2127
- label = new AST.Identifier(this.advance().value)
2128
- }
2129
-
2130
- if (this.match('SEMICOLON')) this.advance()
2131
-
2132
- return new AST.ContinueStatement(label, loc)
2133
- }
2134
-
2135
- parseBlockStatement() {
2136
- const loc = this.peek().loc
2137
- this.expect('LBRACE')
2138
- const body = []
2139
-
2140
- while (!this.match('RBRACE', 'EOF')) {
2141
- body.push(this.parseStatement())
2142
- }
2143
-
2144
- this.expect('RBRACE')
2145
- return new AST.BlockStatement(body, loc)
2146
- }
2147
-
2148
- parseImportDeclaration() {
2149
- const loc = this.peek().loc
2150
- this.advance()
2151
-
2152
- let importKind = 'value'
2153
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'type') {
2154
- importKind = 'type'
2155
- this.advance()
2156
- }
2157
-
2158
- const specifiers = []
2159
-
2160
- if (this.match('STRING')) {
2161
- const source = this.advance()
2162
- if (this.match('SEMICOLON')) this.advance()
2163
- return new AST.ImportDeclaration([], new AST.StringLiteral(source.value, source.raw), importKind, loc)
2164
- }
2165
-
2166
- if (this.match('IDENTIFIER')) {
2167
- specifiers.push(new AST.ImportDefaultSpecifier(new AST.Identifier(this.advance().value)))
2168
-
2169
- if (this.match('COMMA')) {
2170
- this.advance()
2171
- }
2172
- }
2173
-
2174
- if (this.match('TIMES')) {
2175
- this.advance()
2176
- this.expect('KEYWORD')
2177
- specifiers.push(new AST.ImportNamespaceSpecifier(new AST.Identifier(this.expect('IDENTIFIER').value)))
2178
- } else if (this.match('LBRACE')) {
2179
- this.advance()
2180
- while (!this.match('RBRACE', 'EOF')) {
2181
- let specKind = 'value'
2182
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'type') {
2183
- specKind = 'type'
2184
- this.advance()
2185
- }
2186
-
2187
- const imported = new AST.Identifier(this.expect('IDENTIFIER').value)
2188
- let local = imported
2189
-
2190
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'as') {
2191
- this.advance()
2192
- local = new AST.Identifier(this.expect('IDENTIFIER').value)
2193
- }
2194
-
2195
- specifiers.push(new AST.ImportSpecifier(imported, local, specKind))
2196
-
2197
- if (!this.match('RBRACE')) {
2198
- this.expect('COMMA')
2199
- }
2200
- }
2201
- this.expect('RBRACE')
2202
- }
2203
-
2204
- this.expect('KEYWORD')
2205
- const source = this.expect('STRING')
2206
-
2207
- if (this.match('SEMICOLON')) this.advance()
2208
-
2209
- return new AST.ImportDeclaration(specifiers, new AST.StringLiteral(source.value, source.raw), importKind, loc)
2210
- }
2211
-
2212
- parseExportDeclaration() {
2213
- const loc = this.peek().loc
2214
- this.advance()
2215
-
2216
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'default') {
2217
- this.advance()
2218
- const declaration = this.parseExpression()
2219
- if (this.match('SEMICOLON')) this.advance()
2220
- return new AST.ExportDefaultDeclaration(declaration, loc)
2221
- }
2222
-
2223
- if (this.match('TIMES')) {
2224
- this.advance()
2225
- let exported = null
2226
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'as') {
2227
- this.advance()
2228
- exported = new AST.Identifier(this.expect('IDENTIFIER').value)
2229
- }
2230
- this.expect('KEYWORD')
2231
- const source = this.expect('STRING')
2232
- if (this.match('SEMICOLON')) this.advance()
2233
- return new AST.ExportAllDeclaration(new AST.StringLiteral(source.value, source.raw), exported, 'value', loc)
2234
- }
2235
-
2236
- let exportKind = 'value'
2237
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'type') {
2238
- exportKind = 'type'
2239
- this.advance()
2240
- }
2241
-
2242
- if (this.match('LBRACE')) {
2243
- this.advance()
2244
- const specifiers = []
2245
-
2246
- while (!this.match('RBRACE', 'EOF')) {
2247
- const local = new AST.Identifier(this.expect('IDENTIFIER').value)
2248
- let exported = local
2249
-
2250
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'as') {
2251
- this.advance()
2252
- exported = new AST.Identifier(this.expect('IDENTIFIER').value)
2253
- }
2254
-
2255
- specifiers.push(new AST.ExportSpecifier(local, exported, exportKind))
2256
-
2257
- if (!this.match('RBRACE')) {
2258
- this.expect('COMMA')
2259
- }
2260
- }
2261
- this.expect('RBRACE')
2262
-
2263
- let source = null
2264
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'from') {
2265
- this.advance()
2266
- const sourceToken = this.expect('STRING')
2267
- source = new AST.StringLiteral(sourceToken.value, sourceToken.raw)
2268
- }
2269
-
2270
- if (this.match('SEMICOLON')) this.advance()
2271
-
2272
- return new AST.ExportNamedDeclaration(null, specifiers, source, exportKind, loc)
2273
- }
2274
-
2275
- const declaration = this.parseStatement()
2276
- return new AST.ExportNamedDeclaration(declaration, [], null, exportKind, loc)
2277
- }
2278
-
2279
- parseExpression() {
2280
- return this.parseAssignment()
2281
- }
2282
-
2283
- parseAssignment() {
2284
- const left = this.parseConditional()
2285
-
2286
- if (this.match('ASSIGN', 'PLUS_ASSIGN', 'MINUS_ASSIGN', 'TIMES_ASSIGN', 'DIV_ASSIGN', 'MOD_ASSIGN',
2287
- 'POW_ASSIGN', 'AND_ASSIGN', 'OR_ASSIGN', 'NULLISH_ASSIGN',
2288
- 'BIT_AND_ASSIGN', 'BIT_OR_ASSIGN', 'BIT_XOR_ASSIGN',
2289
- 'LEFT_SHIFT_ASSIGN', 'RIGHT_SHIFT_ASSIGN', 'UNSIGNED_RIGHT_SHIFT_ASSIGN')) {
2290
- const op = this.advance()
2291
- const right = this.parseAssignment()
2292
- return new AST.AssignmentExpression(op.value, left, right, left.loc)
2293
- }
2294
-
2295
- return left
2296
- }
2297
-
2298
- parseConditional() {
2299
- const test = this.parseNullish()
2300
-
2301
- if (this.match('QUESTION')) {
2302
- this.advance()
2303
- const consequent = this.parseAssignment()
2304
- this.expect('COLON')
2305
- const alternate = this.parseAssignment()
2306
- return new AST.ConditionalExpression(test, consequent, alternate, test.loc)
2307
- }
2308
-
2309
- return test
2310
- }
2311
-
2312
- parseNullish() {
2313
- let left = this.parseLogicalOr()
2314
-
2315
- while (this.match('NULLISH')) {
2316
- this.advance()
2317
- const right = this.parseLogicalOr()
2318
- left = new AST.LogicalExpression('??', left, right, left.loc)
2319
- }
2320
-
2321
- return left
2322
- }
2323
-
2324
- parseLogicalOr() {
2325
- let left = this.parseLogicalAnd()
2326
-
2327
- while (this.match('OR')) {
2328
- this.advance()
2329
- const right = this.parseLogicalAnd()
2330
- left = new AST.LogicalExpression('||', left, right, left.loc)
2331
- }
2332
-
2333
- return left
2334
- }
2335
-
2336
- parseLogicalAnd() {
2337
- let left = this.parseBitwiseOr()
2338
-
2339
- while (this.match('AND')) {
2340
- this.advance()
2341
- const right = this.parseBitwiseOr()
2342
- left = new AST.LogicalExpression('&&', left, right, left.loc)
2343
- }
2344
-
2345
- return left
2346
- }
2347
-
2348
- parseBitwiseOr() {
2349
- let left = this.parseBitwiseXor()
2350
-
2351
- while (this.match('BIT_OR')) {
2352
- this.advance()
2353
- const right = this.parseBitwiseXor()
2354
- left = new AST.BinaryExpression('|', left, right, left.loc)
2355
- }
2356
-
2357
- return left
2358
- }
2359
-
2360
- parseBitwiseXor() {
2361
- let left = this.parseBitwiseAnd()
2362
-
2363
- while (this.match('BIT_XOR')) {
2364
- this.advance()
2365
- const right = this.parseBitwiseAnd()
2366
- left = new AST.BinaryExpression('^', left, right, left.loc)
2367
- }
2368
-
2369
- return left
2370
- }
2371
-
2372
- parseBitwiseAnd() {
2373
- let left = this.parseEquality()
2374
-
2375
- while (this.match('BIT_AND')) {
2376
- this.advance()
2377
- const right = this.parseEquality()
2378
- left = new AST.BinaryExpression('&', left, right, left.loc)
2379
- }
2380
-
2381
- return left
2382
- }
2383
-
2384
- parseEquality() {
2385
- let left = this.parseRelational()
2386
-
2387
- while (this.match('EQUAL', 'NOT_EQUAL', 'STRICT_EQUAL', 'STRICT_NOT_EQUAL')) {
2388
- const op = this.advance()
2389
- const right = this.parseRelational()
2390
- left = new AST.BinaryExpression(op.value, left, right, left.loc)
2391
- }
2392
-
2393
- return left
2394
- }
2395
-
2396
- parseRelational() {
2397
- let left = this.parseShift()
2398
-
2399
- while (this.match('LT', 'GT', 'LTE', 'GTE') ||
2400
- (this.match('KEYWORD') && (this.translateKeyword(this.peek().value) === 'in' || this.translateKeyword(this.peek().value) === 'instanceof'))) {
2401
- if (this.match('KEYWORD')) {
2402
- const kw = this.translateKeyword(this.advance().value)
2403
- const right = this.parseShift()
2404
- left = new AST.BinaryExpression(kw, left, right, left.loc)
2405
- } else {
2406
- const op = this.advance()
2407
- const right = this.parseShift()
2408
- left = new AST.BinaryExpression(op.value, left, right, left.loc)
2409
- }
2410
- }
2411
-
2412
- return left
2413
- }
2414
-
2415
- parseShift() {
2416
- let left = this.parseAdditive()
2417
-
2418
- while (this.match('LEFT_SHIFT', 'RIGHT_SHIFT', 'UNSIGNED_RIGHT_SHIFT')) {
2419
- const op = this.advance()
2420
- const right = this.parseAdditive()
2421
- left = new AST.BinaryExpression(op.value, left, right, left.loc)
2422
- }
2423
-
2424
- return left
2425
- }
2426
-
2427
- parseAdditive() {
2428
- let left = this.parseMultiplicative()
2429
-
2430
- while (this.match('PLUS', 'MINUS')) {
2431
- const op = this.advance()
2432
- const right = this.parseMultiplicative()
2433
- left = new AST.BinaryExpression(op.value, left, right, left.loc)
2434
- }
2435
-
2436
- return left
2437
- }
2438
-
2439
- parseMultiplicative() {
2440
- let left = this.parseExponential()
2441
-
2442
- while (this.match('TIMES', 'DIV', 'MOD')) {
2443
- const op = this.advance()
2444
- const right = this.parseExponential()
2445
- left = new AST.BinaryExpression(op.value, left, right, left.loc)
2446
- }
2447
-
2448
- return left
2449
- }
2450
-
2451
- parseExponential() {
2452
- const left = this.parseUnary()
2453
-
2454
- if (this.match('POW')) {
2455
- this.advance()
2456
- const right = this.parseExponential()
2457
- return new AST.BinaryExpression('**', left, right, left.loc)
2458
- }
2459
-
2460
- return left
2461
- }
2462
-
2463
- parseUnary() {
2464
- const loc = this.peek().loc
2465
-
2466
- if (this.match('NOT', 'TILDE', 'PLUS', 'MINUS')) {
2467
- const op = this.advance()
2468
- return new AST.UnaryExpression(op.value, this.parseUnary(), true, loc)
2469
- }
2470
-
2471
- if (this.match('INCREMENT', 'DECREMENT')) {
2472
- const op = this.advance()
2473
- return new AST.UpdateExpression(op.value, this.parseUnary(), true, loc)
2474
- }
2475
-
2476
- if (this.match('KEYWORD')) {
2477
- const kw = this.translateKeyword(this.peek().value)
2478
- if (kw === 'typeof' || kw === 'void' || kw === 'delete') {
2479
- this.advance()
2480
- return new AST.UnaryExpression(kw, this.parseUnary(), true, loc)
2481
- }
2482
- if (kw === 'await') {
2483
- this.advance()
2484
- return new AST.AwaitExpression(this.parseUnary(), loc)
2485
- }
2486
- }
2487
-
2488
- return this.parsePostfix()
2489
- }
2490
-
2491
- parsePostfix() {
2492
- let expr = this.parseCall()
2493
-
2494
- if (this.match('INCREMENT', 'DECREMENT')) {
2495
- const op = this.advance()
2496
- return new AST.UpdateExpression(op.value, expr, false, expr.loc)
2497
- }
2498
-
2499
- if (this.match('NOT')) {
2500
- this.advance()
2501
- return new AST.TSNonNullExpression(expr, expr.loc)
2502
- }
2503
-
2504
- if (this.match('KEYWORD')) {
2505
- const kw = this.translateKeyword(this.peek().value)
2506
- if (kw === 'as') {
2507
- this.advance()
2508
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'const') {
2509
- this.advance()
2510
- return new AST.TSAsExpression(expr, new AST.TSTypeReference(new AST.Identifier('const')))
2511
- }
2512
- const type = this.parseType()
2513
- return new AST.TSAsExpression(expr, type, expr.loc)
2514
- }
2515
- if (kw === 'satisfies') {
2516
- this.advance()
2517
- const type = this.parseType()
2518
- return new AST.TSSatisfiesExpression(expr, type, expr.loc)
2519
- }
2520
- }
2521
-
2522
- return expr
2523
- }
2524
-
2525
- parseCall() {
2526
- let expr = this.parseMember()
2527
-
2528
- while (true) {
2529
- if (this.match('LPAREN')) {
2530
- this.advance()
2531
- const args = []
2532
- while (!this.match('RPAREN', 'EOF')) {
2533
- if (this.match('SPREAD')) {
2534
- this.advance()
2535
- args.push(new AST.SpreadElement(this.parseAssignment()))
2536
- } else {
2537
- args.push(this.parseAssignment())
2538
- }
2539
- if (!this.match('RPAREN')) {
2540
- this.expect('COMMA')
2541
- }
2542
- }
2543
- this.expect('RPAREN')
2544
- expr = new AST.CallExpression(expr, args, false, expr.loc)
2545
- } else if (this.match('OPTIONAL_CHAIN')) {
2546
- this.advance()
2547
- if (this.match('LPAREN')) {
2548
- this.advance()
2549
- const args = []
2550
- while (!this.match('RPAREN', 'EOF')) {
2551
- args.push(this.parseAssignment())
2552
- if (!this.match('RPAREN')) {
2553
- this.expect('COMMA')
2554
- }
2555
- }
2556
- this.expect('RPAREN')
2557
- expr = new AST.CallExpression(expr, args, true, expr.loc)
2558
- } else if (this.match('LBRACKET')) {
2559
- this.advance()
2560
- const property = this.parseExpression()
2561
- this.expect('RBRACKET')
2562
- expr = new AST.MemberExpression(expr, property, true, true, expr.loc)
2563
- } else {
2564
- const property = new AST.Identifier(this.expect('IDENTIFIER').value)
2565
- expr = new AST.MemberExpression(expr, property, false, true, expr.loc)
2566
- }
2567
- } else if (this.match('LT') && this.looksLikeTypeArguments()) {
2568
- const typeArgs = this.parseTypeArguments()
2569
- expr = new AST.TSInstantiationExpression(expr, typeArgs, expr.loc)
2570
- } else {
2571
- break
2572
- }
2573
- }
2574
-
2575
- return expr
2576
- }
2577
-
2578
- looksLikeTypeArguments() {
2579
- let pos = this.pos
2580
- let depth = 1
2581
- pos++
2582
-
2583
- while (pos < this.tokens.length && depth > 0) {
2584
- const t = this.tokens[pos]
2585
- if (t.type === 'LT') depth++
2586
- else if (t.type === 'GT') depth--
2587
- pos++
2588
- }
2589
-
2590
- if (depth !== 0) return false
2591
-
2592
- const next = this.tokens[pos]
2593
- return next && (next.type === 'LPAREN' || next.type === 'DOT' || next.type === 'SEMICOLON' || next.type === 'COMMA' || next.type === 'RPAREN')
2594
- }
2595
-
2596
- parseMember() {
2597
- let expr = this.parsePrimary()
2598
-
2599
- while (true) {
2600
- if (this.match('DOT')) {
2601
- this.advance()
2602
- const property = this.parsePropertyName()
2603
- expr = new AST.MemberExpression(expr, property, false, false, expr.loc)
2604
- } else if (this.match('LBRACKET')) {
2605
- this.advance()
2606
- const property = this.parseExpression()
2607
- this.expect('RBRACKET')
2608
- expr = new AST.MemberExpression(expr, property, true, false, expr.loc)
2609
- } else {
2610
- break
2611
- }
2612
- }
2613
-
2614
- return expr
2615
- }
2616
-
2617
- parsePrimary() {
2618
- const token = this.peek()
2619
- const loc = token.loc
2620
-
2621
- if (token.type === 'IDENTIFIER') {
2622
- this.advance()
2623
- return new AST.Identifier(token.value, loc)
2624
- }
2625
-
2626
- if (token.type === 'NUMBER') {
2627
- this.advance()
2628
- return new AST.NumericLiteral(token.value, token.raw, loc)
2629
- }
2630
-
2631
- if (token.type === 'BIGINT') {
2632
- this.advance()
2633
- return new AST.BigIntLiteral(token.value, token.raw, loc)
2634
- }
2635
-
2636
- if (token.type === 'STRING') {
2637
- this.advance()
2638
- return new AST.StringLiteral(token.value, token.raw, loc)
2639
- }
2640
-
2641
- if (token.type === 'TEMPLATE') {
2642
- this.advance()
2643
- const quasis = token.quasis.map((q, i) => new AST.TemplateElement(q.value, i === token.quasis.length - 1))
2644
- const expressions = token.expressions.map(e => {
2645
- const subParser = new TSParser()
2646
- subParser.tokens = new TSLexer(e).tokenize()
2647
- subParser.pos = 0
2648
- return subParser.parseExpression()
2649
- })
2650
- return new AST.TemplateLiteral(quasis, expressions, loc)
2651
- }
2652
-
2653
- if (token.type === 'PRIVATE_IDENTIFIER') {
2654
- this.advance()
2655
- return new AST.PrivateIdentifier(token.value, loc)
2656
- }
2657
-
2658
- if (token.type === 'KEYWORD') {
2659
- const kw = this.translateKeyword(token.value)
2660
-
2661
- if (kw === 'true') {
2662
- this.advance()
2663
- return new AST.BooleanLiteral(true, loc)
2664
- }
2665
- if (kw === 'false') {
2666
- this.advance()
2667
- return new AST.BooleanLiteral(false, loc)
2668
- }
2669
- if (kw === 'null') {
2670
- this.advance()
2671
- return new AST.NullLiteral(loc)
2672
- }
2673
- if (kw === 'undefined') {
2674
- this.advance()
2675
- return new AST.UndefinedLiteral(loc)
2676
- }
2677
- if (kw === 'this') {
2678
- this.advance()
2679
- return new AST.ThisExpression(loc)
2680
- }
2681
- if (kw === 'super') {
2682
- this.advance()
2683
- return new AST.Super(loc)
2684
- }
2685
- if (kw === 'new') {
2686
- return this.parseNewExpression()
2687
- }
2688
- if (kw === 'function') {
2689
- return this.parseFunctionExpression()
2690
- }
2691
- if (kw === 'class') {
2692
- return this.parseClassExpression()
2693
- }
2694
- if (kw === 'async') {
2695
- if (this.peek(1).type === 'KEYWORD' && this.translateKeyword(this.peek(1).value) === 'function') {
2696
- this.advance()
2697
- return this.parseFunctionExpression(true)
2698
- }
2699
- if (this.peek(1).type === 'LPAREN' || this.peek(1).type === 'IDENTIFIER') {
2700
- return this.parseArrowFunction(true)
2701
- }
2702
- }
2703
- if (kw === 'yield') {
2704
- return this.parseYieldExpression()
2705
- }
2706
- if (kw === 'import') {
2707
- this.advance()
2708
- if (this.match('DOT')) {
2709
- this.advance()
2710
- const property = new AST.Identifier(this.expect('IDENTIFIER').value)
2711
- return new AST.MetaProperty(new AST.Identifier('import'), property, loc)
2712
- }
2713
- this.expect('LPAREN')
2714
- const source = this.parseAssignment()
2715
- this.expect('RPAREN')
2716
- return new AST.ImportExpression(source, loc)
2717
- }
2718
- }
2719
-
2720
- if (this.match('LBRACKET')) {
2721
- return this.parseArrayExpression()
2722
- }
2723
-
2724
- if (this.match('LBRACE')) {
2725
- return this.parseObjectExpression()
2726
- }
2727
-
2728
- if (this.match('LPAREN')) {
2729
- return this.parseParenthesizedOrArrow()
2730
- }
2731
-
2732
- if (this.match('LT')) {
2733
- return this.parseTypeAssertion()
2734
- }
2735
-
2736
- throw new Error(`Token inattendu ${token.type} à ligne ${loc.line}`)
2737
- }
2738
-
2739
- parseNewExpression() {
2740
- const loc = this.peek().loc
2741
- this.advance()
2742
-
2743
- if (this.match('DOT')) {
2744
- this.advance()
2745
- const property = new AST.Identifier(this.expect('IDENTIFIER').value)
2746
- return new AST.MetaProperty(new AST.Identifier('new'), property, loc)
2747
- }
2748
-
2749
- let callee = this.parseMember()
2750
-
2751
- if (this.match('LT')) {
2752
- const typeArgs = this.parseTypeArguments()
2753
- callee = new AST.TSInstantiationExpression(callee, typeArgs)
2754
- }
2755
-
2756
- let args = []
2757
- if (this.match('LPAREN')) {
2758
- this.advance()
2759
- while (!this.match('RPAREN', 'EOF')) {
2760
- if (this.match('SPREAD')) {
2761
- this.advance()
2762
- args.push(new AST.SpreadElement(this.parseAssignment()))
2763
- } else {
2764
- args.push(this.parseAssignment())
2765
- }
2766
- if (!this.match('RPAREN')) {
2767
- this.expect('COMMA')
2768
- }
2769
- }
2770
- this.expect('RPAREN')
2771
- }
2772
-
2773
- return new AST.NewExpression(callee, args, loc)
2774
- }
2775
-
2776
- parseFunctionExpression(async = false) {
2777
- const loc = this.peek().loc
2778
- this.advance()
2779
-
2780
- let generator = false
2781
- if (this.match('TIMES')) {
2782
- generator = true
2783
- this.advance()
2784
- }
2785
-
2786
- let id = null
2787
- if (this.match('IDENTIFIER')) {
2788
- id = new AST.Identifier(this.advance().value)
2789
- }
2790
-
2791
- let typeParameters = null
2792
- if (this.match('LT')) {
2793
- typeParameters = this.parseTypeParameters()
2794
- }
2795
-
2796
- this.expect('LPAREN')
2797
- const params = this.parseParameterList()
2798
- this.expect('RPAREN')
2799
-
2800
- let returnType = null
2801
- if (this.match('COLON')) {
2802
- this.advance()
2803
- returnType = new AST.TSTypeAnnotation(this.parseType())
2804
- }
2805
-
2806
- const body = this.parseBlockStatement()
2807
-
2808
- return new AST.FunctionExpression(id, params, body, async, generator, returnType, typeParameters, loc)
2809
- }
2810
-
2811
- parseClassExpression() {
2812
- const loc = this.peek().loc
2813
- this.advance()
2814
-
2815
- let id = null
2816
- if (this.match('IDENTIFIER')) {
2817
- id = new AST.Identifier(this.advance().value)
2818
- }
2819
-
2820
- let typeParameters = null
2821
- if (this.match('LT')) {
2822
- typeParameters = this.parseTypeParameters()
2823
- }
2824
-
2825
- let superClass = null
2826
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'extends') {
2827
- this.advance()
2828
- superClass = this.parseIdentifierOrQualifiedName()
2829
- }
2830
-
2831
- const implements_ = []
2832
- if (this.match('KEYWORD') && this.translateKeyword(this.peek().value) === 'implements') {
2833
- this.advance()
2834
- implements_.push(this.parseInterfaceHeritage())
2835
- while (this.match('COMMA')) {
2836
- this.advance()
2837
- implements_.push(this.parseInterfaceHeritage())
2838
- }
2839
- }
2840
-
2841
- const body = this.parseClassBody()
2842
-
2843
- return new AST.ClassExpression(id, body, superClass, implements_, [], false, typeParameters, loc)
2844
- }
2845
-
2846
- parseYieldExpression() {
2847
- const loc = this.peek().loc
2848
- this.advance()
2849
-
2850
- let delegate = false
2851
- if (this.match('TIMES')) {
2852
- delegate = true
2853
- this.advance()
2854
- }
2855
-
2856
- let argument = null
2857
- if (!this.match('SEMICOLON', 'RPAREN', 'RBRACKET', 'COMMA', 'RBRACE', 'COLON')) {
2858
- argument = this.parseAssignment()
2859
- }
2860
-
2861
- return new AST.YieldExpression(argument, delegate, loc)
2862
- }
2863
-
2864
- parseArrayExpression() {
2865
- const loc = this.peek().loc
2866
- this.expect('LBRACKET')
2867
- const elements = []
2868
-
2869
- while (!this.match('RBRACKET', 'EOF')) {
2870
- if (this.match('COMMA')) {
2871
- elements.push(null)
2872
- this.advance()
2873
- continue
2874
- }
2875
-
2876
- if (this.match('SPREAD')) {
2877
- this.advance()
2878
- elements.push(new AST.SpreadElement(this.parseAssignment()))
2879
- } else {
2880
- elements.push(this.parseAssignment())
2881
- }
2882
-
2883
- if (!this.match('RBRACKET')) {
2884
- this.expect('COMMA')
2885
- }
2886
- }
2887
-
2888
- this.expect('RBRACKET')
2889
- return new AST.ArrayExpression(elements, loc)
2890
- }
2891
-
2892
- parseObjectExpression() {
2893
- const loc = this.peek().loc
2894
- this.expect('LBRACE')
2895
- const properties = []
2896
-
2897
- while (!this.match('RBRACE', 'EOF')) {
2898
- if (this.match('SPREAD')) {
2899
- this.advance()
2900
- properties.push(new AST.SpreadElement(this.parseAssignment()))
2901
- } else {
2902
- properties.push(this.parsePropertyDefinition())
2903
- }
2904
-
2905
- if (!this.match('RBRACE')) {
2906
- this.expect('COMMA')
2907
- }
2908
- }
2909
-
2910
- this.expect('RBRACE')
2911
- return new AST.ObjectExpression(properties, loc)
2912
- }
2913
-
2914
- parsePropertyDefinition() {
2915
- const loc = this.peek().loc
2916
- let computed = false
2917
- let method = false
2918
- let shorthand = false
2919
- let kind = 'init'
2920
-
2921
- if (this.match('KEYWORD')) {
2922
- const kw = this.translateKeyword(this.peek().value)
2923
- if (kw === 'get' || kw === 'set') {
2924
- kind = kw
2925
- this.advance()
2926
- } else if (kw === 'async') {
2927
- this.advance()
2928
- const key = this.parsePropertyName()
2929
- return this.parseMethodProperty(key, true, false, loc)
2930
- }
2931
- }
2932
-
2933
- if (this.match('TIMES')) {
2934
- this.advance()
2935
- const key = this.parsePropertyName()
2936
- return this.parseMethodProperty(key, false, true, loc)
2937
- }
2938
-
2939
- const key = this.parsePropertyName()
2940
-
2941
- if (kind !== 'init') {
2942
- return this.parseAccessorProperty(kind, key, loc)
2943
- }
2944
-
2945
- if (this.match('LPAREN') || this.match('LT')) {
2946
- return this.parseMethodProperty(key, false, false, loc)
2947
- }
2948
-
2949
- if (this.match('COLON')) {
2950
- this.advance()
2951
- const value = this.parseAssignment()
2952
- return new AST.Property(key, value, 'init', key.type !== 'Identifier', false, false, loc)
2953
- }
2954
-
2955
- if (this.match('ASSIGN')) {
2956
- this.advance()
2957
- const value = this.parseAssignment()
2958
- return new AST.Property(key, new AST.AssignmentPattern(key, value), 'init', false, true, false, loc)
2959
- }
2960
-
2961
- return new AST.Property(key, key, 'init', false, true, false, loc)
2962
- }
2963
-
2964
- parseMethodProperty(key, async, generator, loc) {
2965
- let typeParameters = null
2966
- if (this.match('LT')) {
2967
- typeParameters = this.parseTypeParameters()
2968
- }
2969
-
2970
- this.expect('LPAREN')
2971
- const params = this.parseParameterList()
2972
- this.expect('RPAREN')
2973
-
2974
- let returnType = null
2975
- if (this.match('COLON')) {
2976
- this.advance()
2977
- returnType = new AST.TSTypeAnnotation(this.parseType())
2978
- }
2979
-
2980
- const body = this.parseBlockStatement()
2981
-
2982
- const value = new AST.FunctionExpression(null, params, body, async, generator, returnType, typeParameters)
2983
- return new AST.Property(key, value, 'init', key.type !== 'Identifier', false, true, loc)
2984
- }
2985
-
2986
- parseAccessorProperty(kind, key, loc) {
2987
- this.expect('LPAREN')
2988
- const params = kind === 'set' ? [this.parseParameter()] : []
2989
- this.expect('RPAREN')
2990
-
2991
- let returnType = null
2992
- if (this.match('COLON')) {
2993
- this.advance()
2994
- returnType = new AST.TSTypeAnnotation(this.parseType())
2995
- }
2996
-
2997
- const body = this.parseBlockStatement()
2998
-
2999
- const value = new AST.FunctionExpression(null, params, body, false, false, returnType)
3000
- return new AST.Property(key, value, kind, key.type !== 'Identifier', false, false, loc)
3001
- }
3002
-
3003
- parseParenthesizedOrArrow() {
3004
- const loc = this.peek().loc
3005
- const startPos = this.pos
3006
-
3007
- this.expect('LPAREN')
3008
-
3009
- if (this.match('RPAREN')) {
3010
- this.advance()
3011
- if (this.match('ARROW') || this.match('COLON')) {
3012
- return this.parseArrowFunctionRest([], false, loc)
3013
- }
3014
- this.pos = startPos
3015
- } else {
3016
- const items = []
3017
- let mightBeArrow = true
3018
-
3019
- while (!this.match('RPAREN', 'EOF') && mightBeArrow) {
3020
- if (this.match('SPREAD')) {
3021
- this.advance()
3022
- items.push({ type: 'rest', value: this.parseBindingPattern() })
3023
- break
3024
- }
3025
-
3026
- const expr = this.parseAssignment()
3027
- items.push({ type: 'expr', value: expr })
3028
-
3029
- if (!this.match('RPAREN')) {
3030
- if (this.match('COMMA')) {
3031
- this.advance()
3032
- } else {
3033
- mightBeArrow = false
3034
- }
3035
- }
3036
- }
3037
-
3038
- if (this.match('RPAREN')) {
3039
- this.advance()
3040
-
3041
- if (this.match('ARROW') || this.match('COLON')) {
3042
- const params = items.map(item => {
3043
- if (item.type === 'rest') {
3044
- return new AST.RestElement(item.value)
3045
- }
3046
- return this.expressionToPattern(item.value)
3047
- })
3048
- return this.parseArrowFunctionRest(params, false, loc)
3049
- }
3050
- }
3051
-
3052
- this.pos = startPos
3053
- }
3054
-
3055
- this.expect('LPAREN')
3056
- const expr = this.parseExpression()
3057
- this.expect('RPAREN')
3058
- return expr
3059
- }
3060
-
3061
- expressionToPattern(expr) {
3062
- if (expr.type === 'Identifier') return expr
3063
- if (expr.type === 'AssignmentExpression' && expr.operator === '=') {
3064
- return new AST.AssignmentPattern(this.expressionToPattern(expr.left), expr.right)
3065
- }
3066
- if (expr.type === 'ArrayExpression') {
3067
- return new AST.ArrayPattern(expr.elements.map(e => e ? this.expressionToPattern(e) : null))
3068
- }
3069
- if (expr.type === 'ObjectExpression') {
3070
- return new AST.ObjectPattern(expr.properties.map(p => {
3071
- if (p.type === 'SpreadElement') {
3072
- return new AST.RestElement(this.expressionToPattern(p.argument))
3073
- }
3074
- return new AST.Property(p.key, this.expressionToPattern(p.value), p.kind, p.computed, p.shorthand, p.method)
3075
- }))
3076
- }
3077
- return expr
3078
- }
3079
-
3080
- parseArrowFunction(async = false) {
3081
- const loc = this.peek().loc
3082
-
3083
- if (async) this.advance()
3084
-
3085
- if (this.match('IDENTIFIER')) {
3086
- const param = new AST.Identifier(this.advance().value)
3087
- this.expect('ARROW')
3088
- const body = this.match('LBRACE') ? this.parseBlockStatement() : this.parseAssignment()
3089
- return new AST.ArrowFunctionExpression([param], body, async, body.type !== 'BlockStatement', null, null, loc)
3090
- }
3091
-
3092
- this.expect('LPAREN')
3093
- const params = this.parseParameterList()
3094
- this.expect('RPAREN')
3095
-
3096
- return this.parseArrowFunctionRest(params, async, loc)
3097
- }
3098
-
3099
- parseArrowFunctionRest(params, async, loc) {
3100
- let returnType = null
3101
- if (this.match('COLON')) {
3102
- this.advance()
3103
- returnType = new AST.TSTypeAnnotation(this.parseType())
3104
- }
3105
-
3106
- this.expect('ARROW')
3107
-
3108
- const body = this.match('LBRACE') ? this.parseBlockStatement() : this.parseAssignment()
3109
-
3110
- return new AST.ArrowFunctionExpression(params, body, async, body.type !== 'BlockStatement', returnType, null, loc)
3111
- }
3112
-
3113
- parseTypeAssertion() {
3114
- const loc = this.peek().loc
3115
- this.expect('LT')
3116
- const type = this.parseType()
3117
- this.expect('GT')
3118
- const expression = this.parseUnary()
3119
- return new AST.TSTypeAssertion(type, expression, loc)
3120
- }
3121
- }
3122
-
3123
- class TSCodeGenerator {
3124
- constructor(options = {}) {
3125
- this.indentStr = options.indentStr || ' '
3126
- this.indentLevel = 0
3127
- }
3128
-
3129
- indent() {
3130
- return this.indentStr.repeat(this.indentLevel)
3131
- }
3132
-
3133
- generate(ast) {
3134
- if (!ast) return ''
3135
-
3136
- const method = `generate${ast.type}`
3137
- if (this[method]) {
3138
- return this[method](ast)
3139
- }
3140
-
3141
- return ''
3142
- }
3143
-
3144
- generateProgram(node) {
3145
- return node.body.map(stmt => this.generate(stmt)).join('\n')
3146
- }
3147
-
3148
- generateTSInterfaceDeclaration(node) {
3149
- let result = `${this.indent()}${node.declare ? 'declare ' : ''}interface ${this.generate(node.id)}`
3150
- if (node.typeParameters) result += this.generate(node.typeParameters)
3151
- if (node.extends.length) result += ` extends ${node.extends.map(e => this.generate(e)).join(', ')}`
3152
- result += ' ' + this.generate(node.body)
3153
- return result
3154
- }
3155
-
3156
- generateTSInterfaceBody(node) {
3157
- this.indentLevel++
3158
- const members = node.body.map(m => this.generate(m)).join('\n')
3159
- this.indentLevel--
3160
- return `{\n${members}\n${this.indent()}}`
3161
- }
3162
-
3163
- generateTSInterfaceHeritage(node) {
3164
- let result = this.generate(node.expression)
3165
- if (node.typeParameters) result += this.generate(node.typeParameters)
3166
- return result
3167
- }
3168
-
3169
- generateTSPropertySignature(node) {
3170
- let result = this.indent()
3171
- if (node.readonly) result += 'readonly '
3172
- result += this.generate(node.key)
3173
- if (node.optional) result += '?'
3174
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3175
- result += ';'
3176
- return result
3177
- }
3178
-
3179
- generateTSMethodSignature(node) {
3180
- let result = this.indent() + this.generate(node.key)
3181
- if (node.optional) result += '?'
3182
- if (node.typeParameters) result += this.generate(node.typeParameters)
3183
- result += '(' + node.params.map(p => this.generate(p)).join(', ') + ')'
3184
- if (node.returnType) result += ': ' + this.generate(node.returnType.typeAnnotation)
3185
- result += ';'
3186
- return result
3187
- }
3188
-
3189
- generateTSIndexSignature(node) {
3190
- let result = this.indent()
3191
- if (node.readonly) result += 'readonly '
3192
- result += '['
3193
- result += node.parameters.map(p => `${p.name}: ${this.generate(p.type)}`).join(', ')
3194
- result += ']'
3195
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3196
- result += ';'
3197
- return result
3198
- }
3199
-
3200
- generateTSTypeAliasDeclaration(node) {
3201
- let result = `${this.indent()}${node.declare ? 'declare ' : ''}type ${this.generate(node.id)}`
3202
- if (node.typeParameters) result += this.generate(node.typeParameters)
3203
- result += ' = ' + this.generate(node.typeAnnotation) + ';'
3204
- return result
3205
- }
3206
-
3207
- generateTSEnumDeclaration(node) {
3208
- let result = `${this.indent()}${node.declare ? 'declare ' : ''}${node.const ? 'const ' : ''}enum ${this.generate(node.id)} {\n`
3209
- this.indentLevel++
3210
- result += node.members.map(m => this.generate(m)).join(',\n')
3211
- this.indentLevel--
3212
- result += `\n${this.indent()}}`
3213
- return result
3214
- }
3215
-
3216
- generateTSEnumMember(node) {
3217
- let result = this.indent() + this.generate(node.id)
3218
- if (node.initializer) result += ' = ' + this.generate(node.initializer)
3219
- return result
3220
- }
3221
-
3222
- generateTSModuleDeclaration(node) {
3223
- let result = `${this.indent()}${node.declare ? 'declare ' : ''}${node.global ? 'global' : 'namespace ' + this.generate(node.id)}`
3224
- if (node.body) result += ' ' + this.generate(node.body)
3225
- return result
3226
- }
3227
-
3228
- generateTSModuleBlock(node) {
3229
- this.indentLevel++
3230
- const body = node.body.map(s => this.generate(s)).join('\n')
3231
- this.indentLevel--
3232
- return `{\n${body}\n${this.indent()}}`
3233
- }
3234
-
3235
- generateTSTypeParameterDeclaration(node) {
3236
- return '<' + node.params.map(p => this.generate(p)).join(', ') + '>'
3237
- }
3238
-
3239
- generateTSTypeParameter(node) {
3240
- let result = ''
3241
- if (node.in) result += 'in '
3242
- if (node.out) result += 'out '
3243
- if (node.const) result += 'const '
3244
- result += this.generate(node.name)
3245
- if (node.constraint) result += ' extends ' + this.generate(node.constraint)
3246
- if (node.default) result += ' = ' + this.generate(node.default)
3247
- return result
3248
- }
3249
-
3250
- generateTSTypeParameterInstantiation(node) {
3251
- return '<' + node.params.map(p => this.generate(p)).join(', ') + '>'
3252
- }
3253
-
3254
- generateTSTypeReference(node) {
3255
- let result = this.generate(node.typeName)
3256
- if (node.typeParameters) result += this.generate(node.typeParameters)
3257
- return result
3258
- }
3259
-
3260
- generateTSQualifiedName(node) {
3261
- return this.generate(node.left) + '.' + this.generate(node.right)
3262
- }
3263
-
3264
- generateTSStringKeyword() { return 'string' }
3265
- generateTSNumberKeyword() { return 'number' }
3266
- generateTSBooleanKeyword() { return 'boolean' }
3267
- generateTSBigIntKeyword() { return 'bigint' }
3268
- generateTSSymbolKeyword() { return 'symbol' }
3269
- generateTSObjectKeyword() { return 'object' }
3270
- generateTSAnyKeyword() { return 'any' }
3271
- generateTSUnknownKeyword() { return 'unknown' }
3272
- generateTSNeverKeyword() { return 'never' }
3273
- generateTSVoidKeyword() { return 'void' }
3274
- generateTSUndefinedKeyword() { return 'undefined' }
3275
- generateTSNullKeyword() { return 'null' }
3276
- generateTSThisType() { return 'this' }
3277
-
3278
- generateTSArrayType(node) {
3279
- const elem = this.generate(node.elementType)
3280
- if (node.elementType.type === 'TSUnionType' || node.elementType.type === 'TSIntersectionType') {
3281
- return `(${elem})[]`
3282
- }
3283
- return `${elem}[]`
3284
- }
3285
-
3286
- generateTSTupleType(node) {
3287
- return '[' + node.elementTypes.map(e => this.generate(e)).join(', ') + ']'
3288
- }
3289
-
3290
- generateTSNamedTupleMember(node) {
3291
- return `${this.generate(node.label)}${node.optional ? '?' : ''}: ${this.generate(node.elementType)}`
3292
- }
3293
-
3294
- generateTSOptionalType(node) {
3295
- return this.generate(node.typeAnnotation) + '?'
3296
- }
3297
-
3298
- generateTSRestType(node) {
3299
- return '...' + this.generate(node.typeAnnotation)
3300
- }
3301
-
3302
- generateTSUnionType(node) {
3303
- return node.types.map(t => this.generate(t)).join(' | ')
3304
- }
3305
-
3306
- generateTSIntersectionType(node) {
3307
- return node.types.map(t => this.generate(t)).join(' & ')
3308
- }
3309
-
3310
- generateTSParenthesizedType(node) {
3311
- return '(' + this.generate(node.typeAnnotation) + ')'
3312
- }
3313
-
3314
- generateTSTypeLiteral(node) {
3315
- if (node.members.length === 0) return '{}'
3316
- this.indentLevel++
3317
- const members = node.members.map(m => this.generate(m)).join('\n')
3318
- this.indentLevel--
3319
- return `{\n${members}\n${this.indent()}}`
3320
- }
3321
-
3322
- generateTSFunctionType(node) {
3323
- let result = '('
3324
- result += node.params.map(p => this.generate(p)).join(', ')
3325
- result += ') => '
3326
- result += this.generate(node.returnType?.typeAnnotation || { type: 'TSVoidKeyword' })
3327
- return result
3328
- }
3329
-
3330
- generateTSConstructorType(node) {
3331
- let result = node.abstract ? 'abstract ' : ''
3332
- result += 'new ('
3333
- result += node.params.map(p => this.generate(p)).join(', ')
3334
- result += ') => '
3335
- result += this.generate(node.returnType?.typeAnnotation || { type: 'TSVoidKeyword' })
3336
- return result
3337
- }
3338
-
3339
- generateTSConditionalType(node) {
3340
- return `${this.generate(node.checkType)} extends ${this.generate(node.extendsType)} ? ${this.generate(node.trueType)} : ${this.generate(node.falseType)}`
3341
- }
3342
-
3343
- generateTSInferType(node) {
3344
- return 'infer ' + this.generate(node.typeParameter)
3345
- }
3346
-
3347
- generateTSMappedType(node) {
3348
- let result = '{ '
3349
- if (node.readonly === '+') result += '+readonly '
3350
- else if (node.readonly === '-') result += '-readonly '
3351
- else if (node.readonly) result += 'readonly '
3352
- result += '[' + this.generate(node.typeParameter)
3353
- if (node.nameType) result += ' as ' + this.generate(node.nameType)
3354
- result += ']'
3355
- if (node.optional === '+') result += '+?'
3356
- else if (node.optional === '-') result += '-?'
3357
- else if (node.optional) result += '?'
3358
- result += ': ' + this.generate(node.typeAnnotation)
3359
- result += ' }'
3360
- return result
3361
- }
3362
-
3363
- generateTSIndexedAccessType(node) {
3364
- return `${this.generate(node.objectType)}[${this.generate(node.indexType)}]`
3365
- }
3366
-
3367
- generateTSTypeOperator(node) {
3368
- return `${node.operator} ${this.generate(node.typeAnnotation)}`
3369
- }
3370
-
3371
- generateTSTypePredicate(node) {
3372
- let result = ''
3373
- if (node.asserts) result += 'asserts '
3374
- result += this.generate(node.parameterName)
3375
- if (node.typeAnnotation) result += ' is ' + this.generate(node.typeAnnotation.typeAnnotation)
3376
- return result
3377
- }
3378
-
3379
- generateTSTypeQuery(node) {
3380
- let result = 'typeof ' + this.generate(node.exprName)
3381
- if (node.typeParameters) result += this.generate(node.typeParameters)
3382
- return result
3383
- }
3384
-
3385
- generateTSLiteralType(node) {
3386
- return this.generate(node.literal)
3387
- }
3388
-
3389
- generateTSAsExpression(node) {
3390
- return `${this.generate(node.expression)} as ${this.generate(node.typeAnnotation)}`
3391
- }
3392
-
3393
- generateTSSatisfiesExpression(node) {
3394
- return `${this.generate(node.expression)} satisfies ${this.generate(node.typeAnnotation)}`
3395
- }
3396
-
3397
- generateTSTypeAssertion(node) {
3398
- return `<${this.generate(node.typeAnnotation)}>${this.generate(node.expression)}`
3399
- }
3400
-
3401
- generateTSNonNullExpression(node) {
3402
- return this.generate(node.expression) + '!'
3403
- }
3404
-
3405
- generateTSInstantiationExpression(node) {
3406
- return this.generate(node.expression) + this.generate(node.typeParameters)
3407
- }
3408
-
3409
- generateTSDeclareFunction(node) {
3410
- let result = `${this.indent()}declare function ${this.generate(node.id)}`
3411
- if (node.typeParameters) result += this.generate(node.typeParameters)
3412
- result += '(' + node.params.map(p => this.generate(p)).join(', ') + ')'
3413
- if (node.returnType) result += ': ' + this.generate(node.returnType.typeAnnotation)
3414
- result += ';'
3415
- return result
3416
- }
3417
-
3418
- generateTSParameterProperty(node) {
3419
- let result = ''
3420
- if (node.accessibility) result += node.accessibility + ' '
3421
- if (node.readonly) result += 'readonly '
3422
- if (node.override) result += 'override '
3423
- result += this.generate(node.parameter)
3424
- return result
3425
- }
3426
-
3427
- generateClassDeclaration(node) {
3428
- let result = this.indent()
3429
- for (const dec of (node.decorators || [])) {
3430
- result += this.generate(dec) + '\n' + this.indent()
3431
- }
3432
- if (node.abstract) result += 'abstract '
3433
- result += 'class ' + this.generate(node.id)
3434
- if (node.typeParameters) result += this.generate(node.typeParameters)
3435
- if (node.superClass) {
3436
- result += ' extends ' + this.generate(node.superClass)
3437
- if (node.superTypeParameters) result += this.generate(node.superTypeParameters)
3438
- }
3439
- if (node.implements?.length) result += ' implements ' + node.implements.map(i => this.generate(i)).join(', ')
3440
- result += ' ' + this.generate(node.body)
3441
- return result
3442
- }
3443
-
3444
- generateClassBody(node) {
3445
- this.indentLevel++
3446
- const members = node.body.map(m => this.generate(m)).filter(m => m).join('\n\n')
3447
- this.indentLevel--
3448
- return `{\n${members}\n${this.indent()}}`
3449
- }
3450
-
3451
- generateMethodDefinition(node) {
3452
- let result = this.indent()
3453
- for (const dec of (node.decorators || [])) {
3454
- result += this.generate(dec) + '\n' + this.indent()
3455
- }
3456
- if (node.accessibility) result += node.accessibility + ' '
3457
- if (node.static) result += 'static '
3458
- if (node.abstract) result += 'abstract '
3459
- if (node.override) result += 'override '
3460
- if (node.kind === 'get') result += 'get '
3461
- if (node.kind === 'set') result += 'set '
3462
- result += this.generate(node.key)
3463
- if (node.value) {
3464
- if (node.value.typeParameters) result += this.generate(node.value.typeParameters)
3465
- result += '(' + node.value.params.map(p => this.generate(p)).join(', ') + ')'
3466
- if (node.value.returnType) result += ': ' + this.generate(node.value.returnType.typeAnnotation)
3467
- if (node.value.body) result += ' ' + this.generate(node.value.body)
3468
- else result += ';'
3469
- }
3470
- return result
3471
- }
3472
-
3473
- generatePropertyDefinition(node) {
3474
- let result = this.indent()
3475
- for (const dec of (node.decorators || [])) {
3476
- result += this.generate(dec) + '\n' + this.indent()
3477
- }
3478
- if (node.accessibility) result += node.accessibility + ' '
3479
- if (node.static) result += 'static '
3480
- if (node.abstract) result += 'abstract '
3481
- if (node.override) result += 'override '
3482
- if (node.readonly) result += 'readonly '
3483
- result += this.generate(node.key)
3484
- if (node.optional) result += '?'
3485
- if (node.definite) result += '!'
3486
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3487
- if (node.value) result += ' = ' + this.generate(node.value)
3488
- result += ';'
3489
- return result
3490
- }
3491
-
3492
- generateStaticBlock(node) {
3493
- return `${this.indent()}static ${this.generate(new AST.BlockStatement(node.body))}`
3494
- }
3495
-
3496
- generateDecorator(node) {
3497
- return '@' + this.generate(node.expression)
3498
- }
3499
-
3500
- generateFunctionDeclaration(node) {
3501
- let result = this.indent()
3502
- if (node.async) result += 'async '
3503
- result += 'function '
3504
- if (node.generator) result += '* '
3505
- result += this.generate(node.id)
3506
- if (node.typeParameters) result += this.generate(node.typeParameters)
3507
- result += '(' + node.params.map(p => this.generate(p)).join(', ') + ')'
3508
- if (node.returnType) result += ': ' + this.generate(node.returnType.typeAnnotation)
3509
- result += ' ' + this.generate(node.body)
3510
- return result
3511
- }
3512
-
3513
- generateFunctionExpression(node) {
3514
- let result = ''
3515
- if (node.async) result += 'async '
3516
- result += 'function'
3517
- if (node.generator) result += '*'
3518
- if (node.id) result += ' ' + this.generate(node.id)
3519
- if (node.typeParameters) result += this.generate(node.typeParameters)
3520
- result += '(' + node.params.map(p => this.generate(p)).join(', ') + ')'
3521
- if (node.returnType) result += ': ' + this.generate(node.returnType.typeAnnotation)
3522
- result += ' ' + this.generate(node.body)
3523
- return result
3524
- }
3525
-
3526
- generateArrowFunctionExpression(node) {
3527
- let result = ''
3528
- if (node.async) result += 'async '
3529
- if (node.typeParameters) result += this.generate(node.typeParameters)
3530
- if (node.params.length === 1 && node.params[0].type === 'Identifier' && !node.params[0].typeAnnotation && !node.returnType) {
3531
- result += this.generate(node.params[0])
3532
- } else {
3533
- result += '(' + node.params.map(p => this.generate(p)).join(', ') + ')'
3534
- }
3535
- if (node.returnType) result += ': ' + this.generate(node.returnType.typeAnnotation)
3536
- result += ' => '
3537
- if (node.expression) {
3538
- result += this.generate(node.body)
3539
- } else {
3540
- result += this.generate(node.body)
3541
- }
3542
- return result
3543
- }
3544
-
3545
- generateVariableDeclaration(node) {
3546
- return `${this.indent()}${node.kind} ${node.declarations.map(d => this.generate(d)).join(', ')};`
3547
- }
3548
-
3549
- generateVariableDeclarator(node) {
3550
- let result = this.generate(node.id)
3551
- if (node.init) result += ' = ' + this.generate(node.init)
3552
- return result
3553
- }
3554
-
3555
- generateIdentifier(node) {
3556
- let result = node.name
3557
- if (node.optional) result += '?'
3558
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3559
- return result
3560
- }
3561
-
3562
- generatePrivateIdentifier(node) {
3563
- return '#' + node.name
3564
- }
3565
-
3566
- generateRestElement(node) {
3567
- let result = '...' + this.generate(node.argument)
3568
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3569
- return result
3570
- }
3571
-
3572
- generateAssignmentPattern(node) {
3573
- return this.generate(node.left) + ' = ' + this.generate(node.right)
3574
- }
3575
-
3576
- generateArrayPattern(node) {
3577
- let result = '[' + node.elements.map(e => e ? this.generate(e) : '').join(', ') + ']'
3578
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3579
- return result
3580
- }
3581
-
3582
- generateObjectPattern(node) {
3583
- let result = '{ ' + node.properties.map(p => this.generate(p)).join(', ') + ' }'
3584
- if (node.typeAnnotation) result += ': ' + this.generate(node.typeAnnotation.typeAnnotation)
3585
- return result
3586
- }
3587
-
3588
- generateBlockStatement(node) {
3589
- this.indentLevel++
3590
- const body = node.body.map(s => this.generate(s)).join('\n')
3591
- this.indentLevel--
3592
- return `{\n${body}\n${this.indent()}}`
3593
- }
3594
-
3595
- generateExpressionStatement(node) {
3596
- return this.indent() + this.generate(node.expression) + ';'
3597
- }
3598
-
3599
- generateEmptyStatement() {
3600
- return this.indent() + ';'
3601
- }
3602
-
3603
- generateIfStatement(node) {
3604
- let result = `${this.indent()}if (${this.generate(node.test)}) ${this.generate(node.consequent)}`
3605
- if (node.alternate) {
3606
- result += ` else ${this.generate(node.alternate)}`
3607
- }
3608
- return result
3609
- }
3610
-
3611
- generateSwitchStatement(node) {
3612
- let result = `${this.indent()}switch (${this.generate(node.discriminant)}) {\n`
3613
- this.indentLevel++
3614
- result += node.cases.map(c => this.generate(c)).join('\n')
3615
- this.indentLevel--
3616
- result += `\n${this.indent()}}`
3617
- return result
3618
- }
3619
-
3620
- generateSwitchCase(node) {
3621
- let result = node.test ? `${this.indent()}case ${this.generate(node.test)}:\n` : `${this.indent()}default:\n`
3622
- this.indentLevel++
3623
- result += node.consequent.map(s => this.generate(s)).join('\n')
3624
- this.indentLevel--
3625
- return result
3626
- }
3627
-
3628
- generateForStatement(node) {
3629
- let result = `${this.indent()}for (`
3630
- if (node.init) result += this.generate(node.init).replace(/;$/, '').trim()
3631
- result += '; '
3632
- if (node.test) result += this.generate(node.test)
3633
- result += '; '
3634
- if (node.update) result += this.generate(node.update)
3635
- result += ') ' + this.generate(node.body)
3636
- return result
3637
- }
3638
-
3639
- generateForInStatement(node) {
3640
- const left = this.generate(node.left).replace(/;$/, '').trim()
3641
- return `${this.indent()}for (${left} in ${this.generate(node.right)}) ${this.generate(node.body)}`
3642
- }
3643
-
3644
- generateForOfStatement(node) {
3645
- const left = this.generate(node.left).replace(/;$/, '').trim()
3646
- const await_ = node.await ? 'await ' : ''
3647
- return `${this.indent()}for ${await_}(${left} of ${this.generate(node.right)}) ${this.generate(node.body)}`
3648
- }
3649
-
3650
- generateWhileStatement(node) {
3651
- return `${this.indent()}while (${this.generate(node.test)}) ${this.generate(node.body)}`
3652
- }
3653
-
3654
- generateDoWhileStatement(node) {
3655
- return `${this.indent()}do ${this.generate(node.body)} while (${this.generate(node.test)});`
3656
- }
3657
-
3658
- generateTryStatement(node) {
3659
- let result = `${this.indent()}try ${this.generate(node.block)}`
3660
- if (node.handler) result += ' ' + this.generate(node.handler)
3661
- if (node.finalizer) result += ` finally ${this.generate(node.finalizer)}`
3662
- return result
3663
- }
3664
-
3665
- generateCatchClause(node) {
3666
- let result = 'catch'
3667
- if (node.param) result += ` (${this.generate(node.param)})`
3668
- result += ' ' + this.generate(node.body)
3669
- return result
3670
- }
3671
-
3672
- generateThrowStatement(node) {
3673
- return `${this.indent()}throw ${this.generate(node.argument)};`
3674
- }
3675
-
3676
- generateReturnStatement(node) {
3677
- return `${this.indent()}return${node.argument ? ' ' + this.generate(node.argument) : ''};`
3678
- }
3679
-
3680
- generateBreakStatement(node) {
3681
- return `${this.indent()}break${node.label ? ' ' + this.generate(node.label) : ''};`
3682
- }
3683
-
3684
- generateContinueStatement(node) {
3685
- return `${this.indent()}continue${node.label ? ' ' + this.generate(node.label) : ''};`
3686
- }
3687
-
3688
- generateImportDeclaration(node) {
3689
- let result = this.indent() + 'import '
3690
- if (node.importKind === 'type') result += 'type '
3691
-
3692
- if (node.specifiers.length === 0) {
3693
- result += this.generate(node.source)
3694
- } else {
3695
- const defaultSpec = node.specifiers.find(s => s.type === 'ImportDefaultSpecifier')
3696
- const nsSpec = node.specifiers.find(s => s.type === 'ImportNamespaceSpecifier')
3697
- const namedSpecs = node.specifiers.filter(s => s.type === 'ImportSpecifier')
3698
-
3699
- if (defaultSpec) result += this.generate(defaultSpec.local)
3700
- if (defaultSpec && (nsSpec || namedSpecs.length)) result += ', '
3701
- if (nsSpec) result += '* as ' + this.generate(nsSpec.local)
3702
- if (namedSpecs.length) {
3703
- result += '{ ' + namedSpecs.map(s => {
3704
- let spec = ''
3705
- if (s.importKind === 'type') spec += 'type '
3706
- spec += this.generate(s.imported)
3707
- if (s.imported.name !== s.local.name) spec += ' as ' + this.generate(s.local)
3708
- return spec
3709
- }).join(', ') + ' }'
3710
- }
3711
- result += ' from ' + this.generate(node.source)
3712
- }
3713
- result += ';'
3714
- return result
3715
- }
3716
-
3717
- generateExportNamedDeclaration(node) {
3718
- let result = this.indent() + 'export '
3719
- if (node.exportKind === 'type') result += 'type '
3720
-
3721
- if (node.declaration) {
3722
- result += this.generate(node.declaration).trim()
3723
- } else {
3724
- result += '{ ' + node.specifiers.map(s => {
3725
- let spec = this.generate(s.local)
3726
- if (s.local.name !== s.exported.name) spec += ' as ' + this.generate(s.exported)
3727
- return spec
3728
- }).join(', ') + ' }'
3729
- if (node.source) result += ' from ' + this.generate(node.source)
3730
- result += ';'
3731
- }
3732
- return result
3733
- }
3734
-
3735
- generateExportDefaultDeclaration(node) {
3736
- return `${this.indent()}export default ${this.generate(node.declaration)};`
3737
- }
3738
-
3739
- generateExportAllDeclaration(node) {
3740
- let result = `${this.indent()}export *`
3741
- if (node.exported) result += ' as ' + this.generate(node.exported)
3742
- result += ' from ' + this.generate(node.source) + ';'
3743
- return result
3744
- }
3745
-
3746
- generateBinaryExpression(node) {
3747
- return `${this.generate(node.left)} ${node.operator} ${this.generate(node.right)}`
3748
- }
3749
-
3750
- generateUnaryExpression(node) {
3751
- if (node.prefix) {
3752
- const space = /[a-z]/.test(node.operator) ? ' ' : ''
3753
- return `${node.operator}${space}${this.generate(node.argument)}`
3754
- }
3755
- return `${this.generate(node.argument)}${node.operator}`
3756
- }
3757
-
3758
- generateUpdateExpression(node) {
3759
- if (node.prefix) return `${node.operator}${this.generate(node.argument)}`
3760
- return `${this.generate(node.argument)}${node.operator}`
3761
- }
3762
-
3763
- generateAssignmentExpression(node) {
3764
- return `${this.generate(node.left)} ${node.operator} ${this.generate(node.right)}`
3765
- }
3766
-
3767
- generateLogicalExpression(node) {
3768
- return `${this.generate(node.left)} ${node.operator} ${this.generate(node.right)}`
3769
- }
3770
-
3771
- generateConditionalExpression(node) {
3772
- return `${this.generate(node.test)} ? ${this.generate(node.consequent)} : ${this.generate(node.alternate)}`
3773
- }
3774
-
3775
- generateCallExpression(node) {
3776
- const callee = this.generate(node.callee)
3777
- const args = node.arguments.map(a => this.generate(a)).join(', ')
3778
- return `${callee}${node.optional ? '?.' : ''}(${args})`
3779
- }
3780
-
3781
- generateNewExpression(node) {
3782
- const args = node.arguments.length ? '(' + node.arguments.map(a => this.generate(a)).join(', ') + ')' : ''
3783
- return `new ${this.generate(node.callee)}${args}`
3784
- }
3785
-
3786
- generateMemberExpression(node) {
3787
- const obj = this.generate(node.object)
3788
- const prop = this.generate(node.property)
3789
- const opt = node.optional ? '?.' : ''
3790
- if (node.computed) return `${obj}${opt}[${prop}]`
3791
- return `${obj}${opt || '.'}${prop}`
3792
- }
3793
-
3794
- generateArrayExpression(node) {
3795
- return '[' + node.elements.map(e => e ? this.generate(e) : '').join(', ') + ']'
3796
- }
3797
-
3798
- generateObjectExpression(node) {
3799
- if (node.properties.length === 0) return '{}'
3800
- return '{ ' + node.properties.map(p => this.generate(p)).join(', ') + ' }'
3801
- }
3802
-
3803
- generateProperty(node) {
3804
- if (node.kind === 'get' || node.kind === 'set') {
3805
- return `${node.kind} ${this.generate(node.key)}() ${this.generate(node.value.body)}`
3806
- }
3807
- if (node.method) {
3808
- return `${this.generate(node.key)}(${node.value.params.map(p => this.generate(p)).join(', ')}) ${this.generate(node.value.body)}`
3809
- }
3810
- if (node.shorthand) {
3811
- return this.generate(node.key)
3812
- }
3813
- const key = node.computed ? `[${this.generate(node.key)}]` : this.generate(node.key)
3814
- return `${key}: ${this.generate(node.value)}`
3815
- }
3816
-
3817
- generateSpreadElement(node) {
3818
- return '...' + this.generate(node.argument)
3819
- }
3820
-
3821
- generateTemplateLiteral(node) {
3822
- let result = '`'
3823
- for (let i = 0; i < node.quasis.length; i++) {
3824
- result += node.quasis[i].value
3825
- if (i < node.expressions.length) {
3826
- result += '${' + this.generate(node.expressions[i]) + '}'
3827
- }
3828
- }
3829
- result += '`'
3830
- return result
3831
- }
3832
-
3833
- generateAwaitExpression(node) {
3834
- return 'await ' + this.generate(node.argument)
3835
- }
3836
-
3837
- generateYieldExpression(node) {
3838
- let result = 'yield'
3839
- if (node.delegate) result += '*'
3840
- if (node.argument) result += ' ' + this.generate(node.argument)
3841
- return result
3842
- }
3843
-
3844
- generateThisExpression() { return 'this' }
3845
- generateSuper() { return 'super' }
3846
-
3847
- generateMetaProperty(node) {
3848
- return `${this.generate(node.meta)}.${this.generate(node.property)}`
3849
- }
3850
-
3851
- generateImportExpression(node) {
3852
- return `import(${this.generate(node.source)})`
3853
- }
3854
-
3855
- generateStringLiteral(node) {
3856
- return node.raw || `"${node.value}"`
3857
- }
3858
-
3859
- generateNumericLiteral(node) {
3860
- return node.raw || String(node.value)
3861
- }
3862
-
3863
- generateBigIntLiteral(node) {
3864
- return node.raw || node.value + 'n'
3865
- }
3866
-
3867
- generateBooleanLiteral(node) {
3868
- return node.value ? 'true' : 'false'
3869
- }
3870
-
3871
- generateNullLiteral() { return 'null' }
3872
- generateUndefinedLiteral() { return 'undefined' }
3873
- }
3874
-
3875
- module.exports = {
3876
- TSLexer,
3877
- TSParser,
3878
- TSCodeGenerator,
3879
- TS_KEYWORDS,
3880
- TS_TYPES
3881
- }