Skip to content

Commit 493af70

Browse files
committed
refactor(language-core): reduce script codegen function call branches
1 parent ebb2fb2 commit 493af70

File tree

7 files changed

+261
-261
lines changed

7 files changed

+261
-261
lines changed

packages/language-core/lib/codegen/names.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ export const EmitProps = '__VLS_EmitProps';
2626
export const InternalProps = '__VLS_InternalProps';
2727
export const Emit = '__VLS_Emit';
2828
export const Bindings = '__VLS_Bindings';
29+
export const PublicProps = '__VLS_PublicProps';
2930

3031
export const PROPS_FALLBACK = '__VLS_PROPS_FALLBACK';

packages/language-core/lib/codegen/script/component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export function* generateComponent(
3232
}
3333

3434
const returns: string[][] = [];
35-
if (ctx.bypassDefineComponent) {
35+
const isJs = options.lang === 'js' || options.lang === 'jsx';
36+
if (isJs) {
3637
// fill $props
3738
if (scriptSetupRanges.defineProps) {
3839
const name = scriptSetupRanges.defineProps.name ?? names.props;
@@ -54,7 +55,7 @@ export function* generateComponent(
5455
yield `),${newLine}`;
5556
}
5657

57-
if (!ctx.bypassDefineComponent) {
58+
if (!isJs) {
5859
const emitOptionCodes = [...generateEmitsOption(options, scriptSetupRanges)];
5960
yield* emitOptionCodes;
6061
yield* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, !!emitOptionCodes.length);
@@ -135,13 +136,13 @@ function* generatePropsOption(
135136
}
136137
if (ctx.generatedPropsType) {
137138
if (options.vueCompilerOptions.target < 3.6) {
138-
let propsType = `${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`;
139+
let propsType = `${ctx.localTypes.TypePropsToOption}<${names.PublicProps}>`;
139140
if (scriptSetupRanges.withDefaults?.arg) {
140141
propsType = `${ctx.localTypes.WithDefaultsLocal}<${propsType}, typeof ${names.defaults}>`;
141142
}
142143
optionGenerates.push([`{} as ${propsType}`]);
143144
}
144-
typeOptionGenerates.push([`{} as __VLS_PublicProps`]);
145+
typeOptionGenerates.push([`{} as ${names.PublicProps}`]);
145146
}
146147
if (scriptSetupRanges.defineProps?.arg) {
147148
const { arg } = scriptSetupRanges.defineProps;

packages/language-core/lib/codegen/script/context.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ export function createScriptCodegenContext(options: ScriptCodegenOptions) {
99
const inlayHints: InlayHintInfo[] = [];
1010

1111
return {
12-
generatedTemplate: false,
1312
generatedPropsType: false,
14-
bypassDefineComponent: options.lang === 'js' || options.lang === 'jsx',
1513
bindingNames: new Set([
1614
...options.scriptRanges?.bindings.map(
1715
({ range }) => options.script!.content.slice(range.start, range.end),

packages/language-core/lib/codegen/script/index.ts

Lines changed: 120 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import type { TemplateCodegenContext } from '../template/context';
99
import { endOfLine, generateSfcBlockSection, newLine } from '../utils';
1010
import { endBoundary, startBoundary } from '../utils/boundary';
1111
import { createScriptCodegenContext, type ScriptCodegenContext } from './context';
12-
import { generateScriptSetup, generateScriptSetupImports } from './scriptSetup';
12+
import { generateGeneric, generateScriptSetupImports, generateSetupFunction } from './scriptSetup';
1313
import { generateSrc } from './src';
1414
import { generateTemplate } from './template';
1515

16+
const exportExpression = `{} as typeof ${names._export}`;
17+
1618
export interface ScriptCodegenOptions {
1719
ts: typeof ts;
1820
vueCompilerOptions: VueCompilerOptions;
@@ -35,47 +37,129 @@ export { generate as generateScript };
3537

3638
function generate(options: ScriptCodegenOptions) {
3739
const context = createScriptCodegenContext(options);
38-
const codegen = generateScript(options, context);
40+
const codegen = generateWorker(options, context);
3941

4042
return {
4143
...context,
4244
codes: [...codegen],
4345
};
4446
}
4547

46-
function* generateScript(
48+
function* generateWorker(
4749
options: ScriptCodegenOptions,
4850
ctx: ScriptCodegenContext,
4951
): Generator<Code> {
5052
yield* generateGlobalTypesReference(options);
5153

52-
if (options.scriptSetup && options.scriptSetupRanges) {
53-
yield* generateScriptSetupImports(options.scriptSetup, options.scriptSetupRanges);
54+
const { script, scriptRanges, scriptSetup, scriptSetupRanges, vueCompilerOptions } = options;
55+
56+
if (scriptSetup && scriptSetupRanges) {
57+
yield* generateScriptSetupImports(scriptSetup, scriptSetupRanges);
5458
}
55-
if (options.script && options.scriptRanges) {
56-
const { exportDefault, componentOptions } = options.scriptRanges;
57-
if (options.scriptSetup && options.scriptSetupRanges) {
58-
if (exportDefault) {
59-
yield* generateSfcBlockSection(options.script, 0, exportDefault.start, codeFeatures.all, true);
60-
yield* generateScriptSetup(options, ctx, options.scriptSetup, options.scriptSetupRanges);
61-
}
62-
else {
63-
yield* generateSfcBlockSection(options.script, 0, options.script.content.length, codeFeatures.all, true);
64-
yield* generateScriptSetup(options, ctx, options.scriptSetup, options.scriptSetupRanges);
65-
}
59+
if (script?.src) {
60+
yield* generateSrc(script.src);
61+
}
62+
63+
// <script> + <script setup>
64+
if (script && scriptRanges && scriptSetup && scriptSetupRanges) {
65+
// <script> head
66+
const { exportDefault, componentOptions } = scriptRanges;
67+
if (exportDefault) {
68+
yield* generateSfcBlockSection(script, 0, exportDefault.start, codeFeatures.all, true);
69+
}
70+
else {
71+
yield* generateSfcBlockSection(script, 0, script.content.length, codeFeatures.all, true);
72+
}
73+
74+
// <script setup>
75+
yield* generateExportDeclareEqual(scriptSetup);
76+
if (scriptSetup.generic) {
77+
yield* generateGeneric(
78+
options,
79+
ctx,
80+
scriptSetup,
81+
scriptSetupRanges,
82+
scriptSetup.generic,
83+
generateSetupFunction(
84+
options,
85+
ctx,
86+
scriptSetup,
87+
scriptSetupRanges,
88+
generateTemplate(options, ctx),
89+
),
90+
);
91+
}
92+
else {
93+
yield `await (async () => {${newLine}`;
94+
yield* generateSetupFunction(
95+
options,
96+
ctx,
97+
scriptSetup,
98+
scriptSetupRanges,
99+
generateTemplate(options, ctx),
100+
[`return `],
101+
);
102+
yield `})()${endOfLine}`;
103+
}
104+
105+
// <script> tail
106+
if (exportDefault) {
107+
const { expression } = componentOptions ?? exportDefault;
108+
yield* generateSfcBlockSection(script, exportDefault.start, expression.start, codeFeatures.all);
109+
yield exportExpression;
110+
yield* generateSfcBlockSection(script, expression.end, script.content.length, codeFeatures.all);
111+
}
112+
else {
113+
yield `export default ${exportExpression}${endOfLine}`;
114+
}
115+
}
116+
// only <script setup>
117+
else if (scriptSetup && scriptSetupRanges) {
118+
if (scriptSetup.generic) {
119+
yield* generateExportDeclareEqual(scriptSetup);
120+
yield* generateGeneric(
121+
options,
122+
ctx,
123+
scriptSetup,
124+
scriptSetupRanges,
125+
scriptSetup.generic,
126+
generateSetupFunction(
127+
options,
128+
ctx,
129+
scriptSetup,
130+
scriptSetupRanges,
131+
generateTemplate(options, ctx),
132+
),
133+
);
66134
}
67-
else if (exportDefault) {
135+
else {
136+
// no script block, generate script setup code at root
137+
yield* generateSetupFunction(
138+
options,
139+
ctx,
140+
scriptSetup,
141+
scriptSetupRanges,
142+
generateTemplate(options, ctx),
143+
generateExportDeclareEqual(scriptSetup),
144+
);
145+
}
146+
yield `export default ${exportExpression}${endOfLine}`;
147+
}
148+
// only <script>
149+
else if (script && scriptRanges) {
150+
const { exportDefault, componentOptions } = scriptRanges;
151+
if (exportDefault) {
68152
const { expression } = componentOptions ?? exportDefault;
69153

70154
let wrapLeft: string | undefined;
71155
let wrapRight: string | undefined;
72156
if (
73-
options.script.content[expression.start] === '{'
74-
&& options.vueCompilerOptions.optionsWrapper.length
157+
script.content[expression.start] === '{'
158+
&& vueCompilerOptions.optionsWrapper.length
75159
) {
76-
[wrapLeft, wrapRight] = options.vueCompilerOptions.optionsWrapper;
160+
[wrapLeft, wrapRight] = vueCompilerOptions.optionsWrapper;
77161
ctx.inlayHints.push({
78-
blockName: options.script.name,
162+
blockName: script.name,
79163
offset: expression.start,
80164
setting: 'vue.inlayHints.optionsWrapper',
81165
label: wrapLeft || '[Missing optionsWrapper[0]]',
@@ -84,47 +168,42 @@ function* generateScript(
84168
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.',
85169
].join('\n\n'),
86170
}, {
87-
blockName: options.script.name,
171+
blockName: script.name,
88172
offset: expression.end,
89173
setting: 'vue.inlayHints.optionsWrapper',
90174
label: wrapRight || '[Missing optionsWrapper[1]]',
91175
});
92176
}
93177

94-
yield* generateSfcBlockSection(options.script, 0, exportDefault.start, codeFeatures.all, true);
95-
yield* generateConstExport(options.script);
178+
yield* generateSfcBlockSection(script, 0, exportDefault.start, codeFeatures.all, true);
179+
yield* generateExportDeclareEqual(script);
96180
if (wrapLeft) {
97181
yield wrapLeft;
98182
}
99-
yield* generateSfcBlockSection(options.script, expression.start, expression.end, codeFeatures.all);
183+
yield* generateSfcBlockSection(script, expression.start, expression.end, codeFeatures.all);
100184
if (wrapRight) {
101185
yield wrapRight;
102186
}
103187
yield endOfLine;
188+
yield* generateTemplate(options, ctx);
189+
yield* generateSfcBlockSection(script, exportDefault.start, expression.start, codeFeatures.all);
190+
yield exportExpression;
191+
yield* generateSfcBlockSection(script, expression.end, script.content.length, codeFeatures.all);
104192
}
105193
else {
106-
yield* generateSfcBlockSection(options.script, 0, options.script.content.length, codeFeatures.all, true);
107-
yield* generateConstExport(options.script);
108-
yield `(await import('${options.vueCompilerOptions.lib}')).defineComponent({})${endOfLine}`;
194+
yield* generateSfcBlockSection(script, 0, script.content.length, codeFeatures.all, true);
195+
yield* generateExportDeclareEqual(script);
196+
yield `(await import('${vueCompilerOptions.lib}')).defineComponent({})${endOfLine}`;
197+
yield* generateTemplate(options, ctx);
198+
yield `export default ${exportExpression}${endOfLine}`;
109199
}
110200
}
111-
else if (options.scriptSetup && options.scriptSetupRanges) {
112-
yield* generateScriptSetup(options, ctx, options.scriptSetup, options.scriptSetupRanges);
113-
}
114-
115-
if (!ctx.generatedTemplate) {
116-
yield* generateTemplate(options, ctx);
117-
}
118201

119-
yield* generateExportDefault(options);
120202
yield* ctx.localTypes.generate();
121203
}
122204

123-
function* generateGlobalTypesReference(
124-
options: ScriptCodegenOptions,
125-
): Generator<Code> {
205+
function* generateGlobalTypesReference(options: ScriptCodegenOptions): Generator<Code> {
126206
const globalTypesPath = options.vueCompilerOptions.globalTypesPath(options.fileName);
127-
128207
if (!globalTypesPath) {
129208
yield `/* placeholder */${newLine}`;
130209
}
@@ -144,55 +223,10 @@ function* generateGlobalTypesReference(
144223
}
145224
}
146225

147-
export function* generateConstExport(
148-
block: SfcBlock,
149-
): Generator<Code> {
226+
function* generateExportDeclareEqual(block: SfcBlock): Generator<Code> {
150227
yield `const `;
151228
const token = yield* startBoundary(block.name, 0, codeFeatures.doNotReportTs6133);
152229
yield names._export;
153230
yield endBoundary(token, block.content.length);
154231
yield ` = `;
155232
}
156-
157-
function* generateExportDefault(options: ScriptCodegenOptions): Generator<Code> {
158-
if (options.script?.src) {
159-
yield* generateSrc(options.script.src);
160-
return;
161-
}
162-
163-
const expression = `{} as typeof ${names._export}`;
164-
165-
if (options.script && options.scriptRanges?.exportDefault) {
166-
const { exportDefault, componentOptions } = options.scriptRanges;
167-
yield* generateSfcBlockSection(
168-
options.script,
169-
exportDefault.start,
170-
(componentOptions ?? exportDefault).expression.start,
171-
codeFeatures.all,
172-
);
173-
yield expression;
174-
yield* generateSfcBlockSection(
175-
options.script,
176-
(componentOptions ?? exportDefault).expression.end,
177-
options.script.content.length,
178-
codeFeatures.all,
179-
);
180-
}
181-
else {
182-
yield `export `;
183-
if (options.templateStartTagOffset !== undefined) {
184-
const token = Symbol();
185-
for (let i = 0; i < 'template'.length + 1; i++) {
186-
yield [
187-
``,
188-
'template',
189-
options.templateStartTagOffset + 1 + i,
190-
i === 0
191-
? { ...codeFeatures.navigationWithoutRename, __combineToken: token }
192-
: { __combineToken: token },
193-
];
194-
}
195-
}
196-
yield `default ${expression}${endOfLine}`;
197-
}
198-
}

0 commit comments

Comments
 (0)