Skip to content

Commit 7dfdbb7

Browse files
committed
refactor(generator)!: add CodeGenerator and MsGenerator classes
1 parent 0588f2d commit 7dfdbb7

File tree

12 files changed

+378
-117
lines changed

12 files changed

+378
-117
lines changed

src/core/context/generator.ts

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import type { Generate, SimpleNode } from '../../types'
2+
import type { GeneratorOptions } from './generator'
3+
import { Generator } from './generator'
4+
5+
export interface CodeGeneratorOptions extends GeneratorOptions { }
6+
7+
/**
8+
* 纯代码生成器
9+
* 从 AST 节点生成代码字符串,不依赖 MagicString
10+
*/
11+
export class CodeGenerator extends Generator {
12+
private generatedCode: string[] = []
13+
14+
/**
15+
* 添加代码片段到生成结果
16+
*/
17+
append(code: string): void {
18+
this.generatedCode.push(code)
19+
}
20+
21+
/**
22+
* 处理 CodeStatement 节点
23+
*/
24+
protected handleCodeStatement(node: SimpleNode): void {
25+
this.append(node.value)
26+
}
27+
28+
/**
29+
* 处理自定义生成器返回的结果
30+
*/
31+
protected handleGeneratorResult(node: SimpleNode, result: string): void {
32+
this.append(result)
33+
}
34+
35+
/**
36+
* 保留节点(用于 unhandled: 'keep' 策略)
37+
*/
38+
protected handleKeepNode(node: SimpleNode): void {
39+
if ('value' in node && typeof node.value === 'string')
40+
this.append(node.value)
41+
}
42+
43+
/**
44+
* 生成最终代码
45+
*/
46+
private generate(): string {
47+
this.generatedCode = []
48+
this.walk(this.node)
49+
return this.generatedCode.join('')
50+
}
51+
52+
/**
53+
* 静态方法:从 AST 节点生成代码
54+
*/
55+
static generate(
56+
node: SimpleNode,
57+
generates: (Generate | undefined)[] = [],
58+
options: CodeGeneratorOptions = {},
59+
): string {
60+
return new CodeGenerator(node, generates, options).generate()
61+
}
62+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import type { Generate, SimpleNode } from '../../types'
2+
import { findComment } from '../../utils'
3+
4+
type UnhandledPolicy = 'throw' | 'keep' | 'remove'
5+
6+
export interface GeneratorOptions {
7+
unhandled?: UnhandledPolicy
8+
}
9+
10+
/**
11+
* 生成器基类
12+
* 提供通用的 AST 遍历和节点处理逻辑
13+
*/
14+
export abstract class Generator {
15+
constructor(
16+
public readonly node: SimpleNode,
17+
public readonly generates: (Generate | undefined)[] = [],
18+
protected readonly options: GeneratorOptions = {},
19+
) { }
20+
21+
/**
22+
* 遍历 AST 节点
23+
*/
24+
walk(node: SimpleNode): void {
25+
switch (node.type) {
26+
case 'Program':
27+
for (const child of node.body)
28+
this.walk(child)
29+
break
30+
case 'CodeStatement':
31+
this.handleCodeStatement(node)
32+
break
33+
default:
34+
this.processWithCustomGenerators(node)
35+
}
36+
}
37+
38+
/**
39+
* 处理 CodeStatement 节点
40+
* 子类需要实现此方法
41+
*/
42+
protected abstract handleCodeStatement(node: SimpleNode): void
43+
44+
/**
45+
* 处理自定义生成器的结果
46+
* 子类需要实现此方法
47+
*/
48+
protected abstract handleGeneratorResult(node: SimpleNode, result: string): void
49+
50+
/**
51+
* 使用自定义生成器处理节点
52+
* 生成器返回值约定:
53+
* - string: 处理该节点
54+
* - null: 已手动处理
55+
* - undefined: 不处理,交给下一个生成器
56+
*/
57+
private processWithCustomGenerators(node: SimpleNode): void {
58+
const comment = node.comment && findComment(node.comment)
59+
60+
for (const generate of this.generates) {
61+
if (!generate)
62+
continue
63+
64+
const result = generate.call(this as any, node, comment as any)
65+
66+
if (result !== undefined) {
67+
if (result !== null)
68+
this.handleGeneratorResult(node, String(result))
69+
return
70+
}
71+
}
72+
73+
this.handleUnprocessedNode(node)
74+
}
75+
76+
/**
77+
* 处理未被任何生成器处理的节点
78+
*/
79+
protected handleUnprocessedNode(node: SimpleNode): void {
80+
const policy = this.options.unhandled ?? 'throw'
81+
82+
if (policy === 'remove') {
83+
// 默认删除行为
84+
return
85+
}
86+
87+
if (policy === 'keep') {
88+
// 保留节点
89+
this.handleKeepNode(node)
90+
return
91+
}
92+
93+
throw new Error(
94+
`Generator: Unhandled node type "${node.type}"${node.start != null && node.end != null
95+
? ` at position ${node.start}-${node.end}`
96+
: ''
97+
}`,
98+
)
99+
}
100+
101+
/**
102+
* 保留节点(用于 unhandled: 'keep' 策略)
103+
* 子类需要实现此方法
104+
*/
105+
protected abstract handleKeepNode(node: SimpleNode): void
106+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './code-generator'
2+
export * from './generator'
3+
export * from './ms-generator'

0 commit comments

Comments
 (0)