@vitarx/plugin-vite 0.0.1-alpha.0

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 (42) hide show
  1. package/LICENSE +27 -0
  2. package/README.md +298 -0
  3. package/dist/components.js +1 -0
  4. package/dist/constants/index.js +59 -0
  5. package/dist/context.js +78 -0
  6. package/dist/error.js +156 -0
  7. package/dist/hmr-client/index.js +143 -0
  8. package/dist/hmr-client/update.js +53 -0
  9. package/dist/hmr-client/utils.js +125 -0
  10. package/dist/index.js +65 -0
  11. package/dist/passes/components/ifBlock.js +42 -0
  12. package/dist/passes/components/index.js +24 -0
  13. package/dist/passes/components/switch.js +102 -0
  14. package/dist/passes/directives/index.js +6 -0
  15. package/dist/passes/directives/processDirectives.js +46 -0
  16. package/dist/passes/directives/vIf.js +64 -0
  17. package/dist/passes/hmr/index.js +5 -0
  18. package/dist/passes/hmr/inject.js +189 -0
  19. package/dist/passes/imports/collectImports.js +56 -0
  20. package/dist/passes/imports/collectRefVariables.js +95 -0
  21. package/dist/passes/imports/index.js +7 -0
  22. package/dist/passes/imports/injectImports.js +96 -0
  23. package/dist/passes/index.js +16 -0
  24. package/dist/passes/jsx/index.js +7 -0
  25. package/dist/passes/jsx/processChildren.js +114 -0
  26. package/dist/passes/jsx/processJSXElement.js +173 -0
  27. package/dist/passes/jsx/processJSXFragment.js +37 -0
  28. package/dist/passes/props/attribute.js +165 -0
  29. package/dist/passes/props/index.js +94 -0
  30. package/dist/passes/props/types.js +1 -0
  31. package/dist/passes/props/vmodel.js +115 -0
  32. package/dist/transform.js +144 -0
  33. package/dist/utils/ast-builders.js +142 -0
  34. package/dist/utils/ast-guards.js +16 -0
  35. package/dist/utils/branch-factory.js +107 -0
  36. package/dist/utils/component-collect.js +233 -0
  37. package/dist/utils/generate.js +11 -0
  38. package/dist/utils/index.js +16 -0
  39. package/dist/utils/jsx-helpers.js +168 -0
  40. package/dist/utils/pattern-helpers.js +47 -0
  41. package/dist/utils/vif-helpers.js +127 -0
  42. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ # MIT License
2
+
3
+ ## 版权声明
4
+
5
+ 版权所有 (c) 2024-present 朱冲林
6
+
7
+ ## 许可条款
8
+
9
+ 特此授予任何获得本软件及相关文档文件(以下简称“软件”)副本的个人或组织以下权利,且不受限制地行使以下权利:
10
+
11
+ 1. **使用**:允许在任何用途中使用本软件。
12
+ 2. **复制**:允许复制本软件。
13
+ 3. **修改**:允许修改本软件。
14
+ 4. **合并**:允许将本软件合并到其他作品中。
15
+ 5. **发布**:允许发布本软件。
16
+ 6. **分发**:允许分发本软件。
17
+ 7. **再许可**:允许对本软件进行再许可。
18
+ 8. **销售**:允许销售本软件的副本。
19
+
20
+ ## 条件
21
+
22
+ 上述版权声明和本许可声明须包含在本软件的所有副本或实质性部分中。
23
+
24
+ ## 免责声明
25
+
26
+ 本软件按“原样”提供,不提供任何形式的明示或暗示担保,包括但不限于对适销性、特定用途适用性和非侵权性的担保。
27
+ 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同、侵权或其他行为中产生的,还是与本软件或使用本软件有关的。
package/README.md ADDED
@@ -0,0 +1,298 @@
1
+ # @vitarx/plugin-vite
2
+
3
+ Vitarx 的 Vite 编译插件,提供 JSX 到 `createView` 的编译转换、指令支持和 HMR 热更新功能。
4
+
5
+ ## 特性
6
+
7
+ - 🚀 **JSX 编译** - 将 JSX 语法编译为高效的 `createView` 调用
8
+ - 📦 **编译宏指令** - 支持 `v-if`、`v-else-if`、`v-else`、`v-model`、`v-show` 等指令
9
+ - 🧩 **编译宏组件** - 内置 `Switch`、`Match`、`IfBlock` 纯编译组件
10
+ - 🔥 **HMR 支持** - 开发模式下自动注入热更新代码,支持组件状态保留
11
+ - 📝 **TypeScript** - 完整的 TypeScript 类型支持
12
+
13
+ ## 安装
14
+
15
+ ```bash
16
+ npm install @vitarx/plugin-vite
17
+ # 或
18
+ pnpm add @vitarx/plugin-vite
19
+ # 或
20
+ yarn add @vitarx/plugin-vite
21
+ ```
22
+
23
+ ## 使用方法
24
+
25
+ ### 配置 Vite
26
+
27
+ 在 `vite.config.ts` 中配置插件:
28
+
29
+ ```typescript
30
+ import { defineConfig } from 'vite'
31
+ import vitarx from '@vitarx/plugin-vite'
32
+
33
+ export default defineConfig({
34
+ plugins: [vitarx()]
35
+ })
36
+ ```
37
+
38
+ ### JSX 编译
39
+
40
+ 插件会自动将 JSX 语法编译为 `createView` 调用:
41
+
42
+ ```jsx
43
+ // 编译前
44
+ const App = () => <div className="container">Hello World</div>
45
+
46
+ // 编译后
47
+ import { createView } from 'vitarx'
48
+ const App = () => /* @__PURE__ */createView('div', {
49
+ className: 'container',
50
+ children: 'Hello World'
51
+ })
52
+ ```
53
+
54
+ ## 编译宏指令
55
+
56
+ ### v-if / v-else-if / v-else
57
+
58
+ 条件渲染指令,编译为高效的 `branch` 调用:
59
+
60
+ ```jsx
61
+ <>
62
+ <div v-if={show}>显示内容</div>
63
+ <span v-else-if={other}>其他内容</span>
64
+ <p v-else>默认内容</p>
65
+ </>
66
+ ```
67
+
68
+ 编译后:
69
+
70
+ ```javascript
71
+ branch(
72
+ () => unref(show) ? 0 : unref(other) ? 1 : 2,
73
+ [
74
+ () => createView('div', { children: '显示内容' }),
75
+ () => createView('span', { children: '其他内容' }),
76
+ () => createView('p', { children: '默认内容' })
77
+ ]
78
+ )
79
+ ```
80
+
81
+ ### v-model
82
+
83
+ 双向绑定指令,自动生成 `modelValue` 和 `onUpdate:modelValue`:
84
+
85
+ ```jsx
86
+ <Input v-model={value} />
87
+ ```
88
+
89
+ 编译后:
90
+
91
+ ```javascript
92
+ createView(Input, {
93
+ get modelValue() { return unref(value) },
94
+ 'onUpdate:modelValue': v => { value.value = v }
95
+ })
96
+ ```
97
+
98
+ ### v-show
99
+
100
+ 显示/隐藏指令:
101
+
102
+ ```jsx
103
+ <div v-show={visible}>内容</div>
104
+ ```
105
+
106
+ 编译后:
107
+
108
+ ```javascript
109
+ withDirectives(
110
+ createView('div', { children: '内容' }),
111
+ [['show', { get value() { return unref(visible) } }]]
112
+ )
113
+ ```
114
+
115
+ ## 编译宏组件
116
+
117
+ ### Switch / Match
118
+
119
+ 条件分支组件,类似于 JavaScript 的 switch 语句:
120
+
121
+ ```jsx
122
+ <Switch fallback={<div>默认</div>}>
123
+ <Match when={status === 'loading'}>加载中...</Match>
124
+ <Match when={status === 'error'}>出错了</Match>
125
+ <Match when={status === 'success'}>加载成功</Match>
126
+ </Switch>
127
+ ```
128
+
129
+ 编译后:
130
+
131
+ ```javascript
132
+ branch(
133
+ () => status === 'loading' ? 0 : status === 'error' ? 1 : status === 'success' ? 2 : 3,
134
+ [
135
+ () => '加载中...',
136
+ () => '出错了',
137
+ () => '加载成功',
138
+ () => createView('div', { children: '默认' })
139
+ ]
140
+ )
141
+ ```
142
+
143
+ ### IfBlock
144
+
145
+ 用于包裹 v-if 链,确保类型正确:
146
+
147
+ ```jsx
148
+ <IfBlock>
149
+ <div v-if={a}>A</div>
150
+ <span v-else-if={b}>B</span>
151
+ <p v-else>C</p>
152
+ </IfBlock>
153
+ ```
154
+
155
+ ## Props 处理
156
+
157
+ ### 响应式 Props
158
+
159
+ 插件会自动处理响应式属性:
160
+
161
+ ```jsx
162
+ // ref 变量自动使用 .value
163
+ const count = ref(0);
164
+ <div count={count} />
165
+ // 编译为: get count() { return count.value }
166
+
167
+ // 普通变量自动使用 unref
168
+ <div className={className} />
169
+ // 编译为: get className() { return unref(className) }
170
+
171
+ // 成员表达式直接访问
172
+ <div value={props.value} />
173
+ // 编译为: get value() { return props.value }
174
+ ```
175
+
176
+ ### v-bind 批量绑定
177
+
178
+ ```jsx
179
+ <div {...props} />
180
+ // 或
181
+ <div v-bind={props} />
182
+ ```
183
+
184
+ ## HMR 热更新
185
+
186
+ 开发模式下,插件会自动为导出的组件注入 HMR 支持:
187
+
188
+ ```jsx
189
+ // 编译前
190
+ export const App = () => {
191
+ const count = ref(0)
192
+ return <div>{count}</div>
193
+ }
194
+
195
+ // 编译后(HMR 模式)
196
+ import __$VITARX_HMR$__ from '@vitarx/plugin-vite/hmr-client'
197
+ import { createView as jsxDEV, getInstance } from 'vitarx'
198
+
199
+ export const App = () => {
200
+ const __$VITARX_HMR_VIEW_NODE$__ = getInstance()
201
+ __$VITARX_HMR$__.instance.register(__$VITARX_HMR_VIEW_NODE$__)
202
+ __$VITARX_HMR_VIEW_NODE$__ && Promise.resolve().then(() => {
203
+ __$VITARX_HMR_VIEW_NODE$__._$_VITARX_HMR_VIEW_STATE_$_ = {
204
+ get count() { return count }
205
+ }
206
+ })
207
+ const count = ref(0)
208
+ return jsxDEV('div', { children: count }, { fileName: '...', lineNumber: 5, columnNumber: 10 })
209
+ }
210
+
211
+ __$VITARX_HMR$__.instance.bindId(App, 'abc123')
212
+ import.meta.hot.accept(mod => {
213
+ __$VITARX_HMR$__.instance.update(mod)
214
+ })
215
+ ```
216
+
217
+ ### HMR 组件识别规则
218
+
219
+ 只有满足以下条件的函数才会被注入 HMR 支持:
220
+
221
+ 1. **函数名大写字母开头** - 符合组件命名规范
222
+ 2. **被导出** - 使用 `export` 导出
223
+ 3. **包含 JSX** - 函数体内包含 JSX 语法或返回编译宏组件
224
+
225
+ ## 子元素处理
226
+
227
+ ### 响应式子元素
228
+
229
+ ```jsx
230
+ // 标识符保持原样
231
+ <div>{value}</div>
232
+
233
+ // 成员表达式使用 access
234
+ <div>{props.value}</div>
235
+ // 编译为: access(props, 'value')
236
+
237
+ // 条件表达式使用 branch
238
+ <div>{show ? 'yes' : 'no'}</div>
239
+ // 编译为: branch(() => unref(show) ? 0 : 1, [...])
240
+
241
+ // 逻辑表达式使用 dynamic
242
+ <div>{a && b}</div>
243
+ // 编译为: dynamic(() => a && b)
244
+ ```
245
+
246
+ ## API 参考
247
+
248
+ ### 插件选项
249
+
250
+ ```typescript
251
+ interface VitePluginVitarxOptions {
252
+ // 暂无配置选项
253
+ }
254
+ ```
255
+
256
+ ## 目录结构
257
+
258
+ ```
259
+ src/
260
+ ├── constants/ # 常量定义
261
+ ├── hmr-client/ # HMR 客户端运行时
262
+ ├── passes/ # 编译转换处理
263
+ │ ├── components/ # 编译宏组件
264
+ │ ├── directives/ # 指令处理
265
+ │ ├── hmr/ # HMR 注入
266
+ │ ├── imports/ # 导入处理
267
+ │ ├── jsx/ # JSX 转换
268
+ │ └── props/ # 属性处理
269
+ ├── utils/ # 公共工具函数
270
+ ├── context.ts # 转换上下文
271
+ ├── error.ts # 错误处理
272
+ ├── transform.ts # 主转换入口
273
+ └── index.ts # 插件入口
274
+ ```
275
+
276
+ ## 错误码
277
+
278
+ | 错误码 | 描述 |
279
+ |------|-----------------------------|
280
+ | E001 | 无效的 JSX 属性值 |
281
+ | E002 | 无效的 v-model 值 |
282
+ | E003 | v-else 没有前置的 v-if |
283
+ | E004 | v-else-if 没有前置的 v-if |
284
+ | E005 | 无效的 v-if 值 |
285
+ | E006 | Switch 子元素必须是 Match 组件 |
286
+ | E007 | Match 组件缺少 when 属性 |
287
+ | E008 | IfBlock 子元素必须包含 v-if 指令 |
288
+ | E009 | v-model 与 modelValue 冲突 |
289
+ | E010 | v-model 值必须是标识符或成员表达式 |
290
+ | E011 | v-model Identifier 必须是 ref |
291
+ | E012 | Match 组件必须位于 Switch 组件内部 |
292
+ | E013 | Match 组件必须包含子元素 |
293
+ | E014 | IfBlock 组件必须包含子元素 |
294
+ | E015 | Switch 组件必须包含至少一个 Match 子元素 |
295
+
296
+ ## License
297
+
298
+ MIT
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Vitarx 运行时 API 名称
3
+ * 这些 API 需要从 vitarx 包导入
4
+ */
5
+ export const VITARX_APIS = {
6
+ CREATE_VIEW: 'createView',
7
+ FRAGMENT: 'Fragment',
8
+ BRANCH: 'branch',
9
+ DYNAMIC: 'dynamic',
10
+ ACCESS: 'access',
11
+ WITH_DIRECTIVES: 'withDirectives',
12
+ UNREF: 'unref',
13
+ IS_REF: 'isRef'
14
+ };
15
+ /**
16
+ * Ref 相关 API 名称
17
+ * 用于识别 ref 变量
18
+ */
19
+ export const REF_APIS = {
20
+ REF: 'ref',
21
+ TO_REF: 'toRef',
22
+ TO_REFS: 'toRefs',
23
+ SHALLOW_REF: 'shallowRef',
24
+ COMPUTED: 'computed'
25
+ };
26
+ /**
27
+ * 支持的响应式模块
28
+ * 从这些模块导入的 ref API 会被识别
29
+ */
30
+ export const RESPONSIVE_MODULES = ['vitarx', '@vitarx/responsive'];
31
+ /**
32
+ * 纯编译组件名称
33
+ * 这些组件在编译时会被完全转换
34
+ */
35
+ export const PURE_COMPILE_COMPONENTS = ['Switch', 'Match', 'IfBlock'];
36
+ /**
37
+ * 指令前缀
38
+ */
39
+ export const DIRECTIVE_PREFIX = 'v-';
40
+ /**
41
+ * 纯函数注释
42
+ */
43
+ export const PURE_COMMENT = '@__PURE__';
44
+ /**
45
+ * vitarx 模块名称
46
+ */
47
+ export const VITARX_MODULE = 'vitarx';
48
+ /**
49
+ * 标识符
50
+ */
51
+ export var HMR;
52
+ (function (HMR) {
53
+ HMR["manager"] = "__$VITARX_HMR$__";
54
+ HMR["id"] = "__$VITARX_HMR_COMPONENT_ID$__";
55
+ HMR["view"] = "__$VITARX_HMR_VIEW_NODE$__";
56
+ HMR["state"] = "__$VITARX_HMR_VIEW_STATE$__";
57
+ })(HMR || (HMR = {}));
58
+ /** 默认导出组件基础名称 */
59
+ export const DEFAULT_EXPORT_BASE_NAME = '_defaultExport';
@@ -0,0 +1,78 @@
1
+ /**
2
+ * UI 相关的 API 名称列表
3
+ * 这些 API 用于创建视图,在 HMR 时需要识别
4
+ */
5
+ export const UI_API_NAMES = ['createView', 'branch', 'dynamic', 'access', 'withDirectives'];
6
+ /**
7
+ * 创建转换上下文
8
+ * @param code - 源代码
9
+ * @param id - 文件标识符
10
+ * @param options - 编译选项
11
+ * @param ast - AST 节点
12
+ * @returns 转换上下文对象
13
+ */
14
+ export function createContext(code, id, options, ast) {
15
+ const filename = id.split('?')[0];
16
+ return {
17
+ code,
18
+ id,
19
+ filename,
20
+ options,
21
+ ast,
22
+ imports: {
23
+ createView: false,
24
+ Fragment: false,
25
+ branch: false,
26
+ dynamic: false,
27
+ access: false,
28
+ withDirectives: false,
29
+ unref: false,
30
+ isRef: false
31
+ },
32
+ existingImports: new Set(),
33
+ vitarxAliases: {
34
+ createView: null,
35
+ Fragment: null,
36
+ branch: null,
37
+ dynamic: null,
38
+ access: null,
39
+ withDirectives: null,
40
+ unref: null,
41
+ isRef: null
42
+ },
43
+ refApiAliases: {
44
+ ref: null,
45
+ toRef: null,
46
+ toRefs: null,
47
+ shallowRef: null,
48
+ computed: null
49
+ },
50
+ refVariables: new Set(),
51
+ uiApiAliases: new Set(),
52
+ warnings: []
53
+ };
54
+ }
55
+ /**
56
+ * 标记需要注入的导入
57
+ * @param ctx - 转换上下文
58
+ * @param name - 导入名称
59
+ */
60
+ export function markImport(ctx, name) {
61
+ ctx.imports[name] = true;
62
+ }
63
+ /**
64
+ * 记录 UI API 别名
65
+ * @param ctx - 转换上下文
66
+ * @param alias - API 别名
67
+ */
68
+ export function markUiApiAlias(ctx, alias) {
69
+ ctx.uiApiAliases.add(alias);
70
+ }
71
+ /**
72
+ * 添加编译警告
73
+ * @param ctx - 转换上下文
74
+ * @param warning - 编译警告
75
+ */
76
+ export function addWarning(ctx, warning) {
77
+ ctx.warnings.push(warning);
78
+ }
package/dist/error.js ADDED
@@ -0,0 +1,156 @@
1
+ /**
2
+ * 编译器错误类
3
+ * 包含错误代码和位置信息
4
+ */
5
+ export class CompilerError extends Error {
6
+ constructor(options) {
7
+ super(`[${options.code}] ${options.message}${options.loc ? ` at line ${options.loc.line}:${options.loc.column}` : ''}`);
8
+ /** 错误代码 */
9
+ Object.defineProperty(this, "code", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: void 0
14
+ });
15
+ /** 错误位置 */
16
+ Object.defineProperty(this, "loc", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: void 0
21
+ });
22
+ this.name = 'CompilerError';
23
+ this.code = options.code;
24
+ this.loc = options.loc ?? (options.node?.loc ? {
25
+ line: options.node.loc.start.line,
26
+ column: options.node.loc.start.column
27
+ } : undefined);
28
+ }
29
+ }
30
+ /**
31
+ * 错误代码枚举
32
+ */
33
+ export const ErrorCodes = {
34
+ /** 不能同时使用展开属性和 v-bind */
35
+ E001: 'E001',
36
+ /** 重复的展开属性或属性键 */
37
+ E002: 'E002',
38
+ /** v-else 没有前置的 v-if */
39
+ E003: 'E003',
40
+ /** v-else-if 没有前置的 v-if */
41
+ E004: 'E004',
42
+ /** v-if 链不连续 */
43
+ E005: 'E005',
44
+ /** Switch 组件有无效子节点 */
45
+ E006: 'E006',
46
+ /** Match 组件缺少 when 属性 */
47
+ E007: 'E007',
48
+ /** IfBlock 有无效子元素 */
49
+ E008: 'E008',
50
+ /** v-model 与 modelValue 或 onUpdate:modelValue 冲突 */
51
+ E009: 'E009',
52
+ /** v-model 值必须是 Identifier 或 MemberExpression */
53
+ E010: 'E010',
54
+ /** v-model Identifier 必须是 ref */
55
+ E011: 'E011',
56
+ /** Match 组件必须在 Switch 内使用 */
57
+ E012: 'E012',
58
+ /** Match 组件必须有子元素 */
59
+ E013: 'E013',
60
+ /** IfBlock 组件必须有子元素 */
61
+ E014: 'E014',
62
+ /** Switch 组件必须有 Match 子元素 */
63
+ E015: 'E015',
64
+ };
65
+ /**
66
+ * 警告代码枚举
67
+ */
68
+ export const WarningCodes = {
69
+ /** children 属性和子元素同时存在 */
70
+ W001: 'W001',
71
+ };
72
+ /**
73
+ * 错误消息映射
74
+ */
75
+ export const ErrorMessages = {
76
+ E001: 'Cannot use both spread attribute and v-bind at the same time',
77
+ E002: 'Duplicate spread attributes or duplicate property keys',
78
+ E003: 'v-else found without preceding v-if',
79
+ E004: 'v-else-if found without preceding v-if',
80
+ E005: 'v-if chain is not continuous',
81
+ E006: 'Switch component has invalid child nodes',
82
+ E007: 'Match component is missing "when" attribute',
83
+ E008: 'IfBlock has invalid child elements',
84
+ E009: 'v-model cannot be used with modelValue or onUpdate:modelValue',
85
+ E010: 'v-model value must be an Identifier or MemberExpression',
86
+ E011: 'v-model Identifier must be a ref',
87
+ E012: 'Match component must be used inside Switch',
88
+ E013: 'Match component must have children',
89
+ E014: 'IfBlock component must have children',
90
+ E015: 'Switch component must have at least one Match child',
91
+ };
92
+ /**
93
+ * 警告消息映射
94
+ */
95
+ export const WarningMessages = {
96
+ W001: 'Both "children" attribute and child elements are present. Child elements will take precedence.',
97
+ };
98
+ /**
99
+ * 创建编译错误
100
+ * @param code - 错误代码
101
+ * @param node - 相关 AST 节点
102
+ * @param additionalMessage - 附加消息
103
+ * @returns 编译错误实例
104
+ */
105
+ export function createError(code, node, additionalMessage) {
106
+ const message = ErrorMessages[code] + (additionalMessage ? `: ${additionalMessage}` : '');
107
+ return new CompilerError({ code, message, node });
108
+ }
109
+ /**
110
+ * 编译警告类
111
+ */
112
+ export class CompilerWarning {
113
+ constructor(code, message, loc) {
114
+ /** 警告代码 */
115
+ Object.defineProperty(this, "code", {
116
+ enumerable: true,
117
+ configurable: true,
118
+ writable: true,
119
+ value: void 0
120
+ });
121
+ /** 警告消息 */
122
+ Object.defineProperty(this, "message", {
123
+ enumerable: true,
124
+ configurable: true,
125
+ writable: true,
126
+ value: void 0
127
+ });
128
+ /** 警告位置 */
129
+ Object.defineProperty(this, "loc", {
130
+ enumerable: true,
131
+ configurable: true,
132
+ writable: true,
133
+ value: void 0
134
+ });
135
+ this.code = code;
136
+ this.message = message;
137
+ this.loc = loc;
138
+ }
139
+ toString() {
140
+ return `[${this.code}] ${this.message}${this.loc ? ` at line ${this.loc.line}:${this.loc.column}` : ''}`;
141
+ }
142
+ }
143
+ /**
144
+ * 创建编译警告
145
+ * @param code - 警告代码
146
+ * @param node - 相关 AST 节点
147
+ * @returns 编译警告实例
148
+ */
149
+ export function createWarning(code, node) {
150
+ const message = WarningMessages[code];
151
+ const loc = node?.loc ? {
152
+ line: node.loc.start.line,
153
+ column: node.loc.start.column
154
+ } : undefined;
155
+ return new CompilerWarning(code, message, loc);
156
+ }