Skip to content

Commit 073a7cb

Browse files
authored
perf(language-core): cache and reuse inline ts asts during full updates (#5435)
1 parent 3ee5fb4 commit 073a7cb

19 files changed

+63
-52
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const raw = {
77
semantic: true,
88
navigation: true,
99
},
10-
none: {},
1110
verification: {
1211
verification: true,
1312
},
@@ -45,6 +44,9 @@ const raw = {
4544
completion: true,
4645
semantic: true,
4746
},
47+
semanticWithoutHighlight: {
48+
semantic: { shouldHighlight: () => false },
49+
},
4850
withoutHighlight: {
4951
semantic: { shouldHighlight: () => false },
5052
verification: true,

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ function* generateTemplateBody(
124124
yield* options.templateCodegen.codes;
125125
}
126126
else {
127-
yield `// no template${newLine}`;
128127
if (!options.scriptSetupRanges?.defineSlots) {
129128
yield `type __VLS_Slots = {}${endOfLine}`;
130129
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
281281
offset,
282282
{
283283
...codeFeatures.additionalCompletion,
284-
...codeFeatures.withoutHighlightAndCompletionAndNavigation,
284+
...codeFeatures.semanticWithoutHighlight,
285285
},
286286
];
287287
}

packages/language-core/lib/codegen/template/element.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export function* generateComponent(
5252
let dynamicTagInfo: {
5353
tag: string;
5454
offsets: number[];
55-
astHolder: CompilerDOM.SourceLocation;
5655
} | undefined;
5756

5857
if (isComponentTag) {
@@ -69,7 +68,6 @@ export function* generateComponent(
6968
dynamicTagInfo = {
7069
tag: prop.exp.content,
7170
offsets: [prop.exp.loc.start.offset],
72-
astHolder: prop.exp.loc,
7371
};
7472
props = props.filter(p => p !== prop);
7573
break;
@@ -81,7 +79,6 @@ export function* generateComponent(
8179
dynamicTagInfo = {
8280
tag: node.tag,
8381
offsets: tagOffsets,
84-
astHolder: node.loc,
8582
};
8683
}
8784

@@ -120,7 +117,6 @@ export function* generateComponent(
120117
ctx.codeFeatures.all,
121118
dynamicTagInfo.tag,
122119
dynamicTagInfo.offsets[0],
123-
dynamicTagInfo.astHolder,
124120
`(`,
125121
`)`,
126122
);
@@ -133,7 +129,6 @@ export function* generateComponent(
133129
ctx.codeFeatures.withoutCompletion,
134130
dynamicTagInfo.tag,
135131
dynamicTagInfo.offsets[1],
136-
dynamicTagInfo.astHolder,
137132
`(`,
138133
`)`,
139134
);
@@ -376,7 +371,6 @@ function* generateFailedPropExps(
376371
ctx.codeFeatures.all,
377372
failedExp.node.loc.source,
378373
failedExp.node.loc.start.offset,
379-
failedExp.node.loc,
380374
failedExp.prefix,
381375
failedExp.suffix,
382376
);
@@ -460,7 +454,6 @@ function* generateElementReference(
460454
content,
461455
startOffset,
462456
ctx.codeFeatures.navigation,
463-
prop.value.loc,
464457
);
465458
yield `} */${endOfLine}`;
466459

packages/language-core/lib/codegen/template/elementDirectives.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ function* generateArg(
111111
ctx.codeFeatures.all,
112112
arg.content,
113113
startOffset,
114-
arg.loc,
115114
`(`,
116115
`)`,
117116
);

packages/language-core/lib/codegen/template/elementEvents.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export function* generateEventExpression(
120120
let suffix = `)`;
121121
let isFirstMapping = true;
122122

123-
const ast = createTsAst(options.ts, prop.exp, prop.exp.content);
123+
const ast = createTsAst(options.ts, options.template.ast, prop.exp.content);
124124
const isCompound = isCompoundExpression(options.ts, ast);
125125

126126
if (isCompound) {
@@ -156,7 +156,6 @@ export function* generateEventExpression(
156156
},
157157
prop.exp.content,
158158
prop.exp.loc.start.offset,
159-
prop.exp.loc,
160159
prefix,
161160
suffix,
162161
);
@@ -189,7 +188,6 @@ export function* generateModelEventExpression(
189188
ctx.codeFeatures.verification,
190189
prop.exp.content,
191190
prop.exp.loc.start.offset,
192-
prop.exp.loc,
193191
);
194192
yield ` = $event${endOfLine}`;
195193
yield `}`;

packages/language-core/lib/codegen/template/elementProps.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ export function* generateElementProps(
130130
propName,
131131
prop.arg.loc.start.offset,
132132
codeInfo,
133-
(prop.loc as any).name_2 ??= {},
134133
shouldCamelize,
135134
)
136135
: wrapWith(
@@ -208,7 +207,6 @@ export function* generateElementProps(
208207
prop.name,
209208
prop.loc.start.offset,
210209
codeInfo,
211-
(prop.loc as any).name_1 ??= {},
212210
shouldCamelize,
213211
),
214212
`: `,
@@ -287,7 +285,6 @@ export function* generatePropExp(
287285
features,
288286
exp.loc.source,
289287
exp.loc.start.offset,
290-
exp.loc,
291288
`(`,
292289
`)`,
293290
);

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ function* generateSlots(
8888
slot.name,
8989
slot.offset,
9090
ctx.codeFeatures.withoutHighlightAndCompletion,
91-
slot.nodeLoc,
9291
);
9392
}
9493
else {

packages/language-core/lib/codegen/template/interpolation.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
11
import { isGloballyAllowed, makeMap } from '@vue/shared';
22
import type * as ts from 'typescript';
3-
import type { Code, VueCodeInformation } from '../../types';
3+
import type { Code, Sfc, VueCodeInformation } from '../../types';
44
import { getNodeText, getStartEnd } from '../../utils/shared';
5+
import type { ScriptCodegenOptions } from '../script';
56
import { collectVars, createTsAst, identifierRegex } from '../utils';
67
import type { TemplateCodegenContext } from './context';
8+
import type { TemplateCodegenOptions } from './index';
79

810
// https://github.com/vuejs/core/blob/fb0c3ca519f1fccf52049cd6b8db3a67a669afe9/packages/compiler-core/src/transforms/transformExpression.ts#L47
911
const isLiteralWhitelisted = /*@__PURE__*/ makeMap('true,false,null,this');
1012

1113
export function* generateInterpolation(
12-
options: {
13-
ts: typeof ts,
14-
destructuredPropNames: Set<string> | undefined,
15-
templateRefNames: Set<string> | undefined;
16-
},
14+
options: TemplateCodegenOptions | ScriptCodegenOptions,
1715
ctx: TemplateCodegenContext,
1816
source: string,
1917
data: VueCodeInformation | ((offset: number) => VueCodeInformation) | undefined,
2018
code: string,
2119
start: number | undefined,
22-
astHolder: any = {},
2320
prefix: string = '',
2421
suffix: string = '',
2522
): Generator<Code> {
23+
const {
24+
ts,
25+
destructuredPropNames,
26+
templateRefNames,
27+
} = options;
28+
const template = 'template' in options ? options.template : options.sfc.template;
29+
2630
for (let [section, offset, type] of forEachInterpolationSegment(
27-
options.ts,
28-
options.destructuredPropNames,
29-
options.templateRefNames,
31+
ts,
32+
template,
33+
destructuredPropNames,
34+
templateRefNames,
3035
ctx,
3136
code,
3237
start,
33-
astHolder,
3438
prefix,
3539
suffix,
3640
)) {
@@ -88,12 +92,12 @@ type Segment = [
8892

8993
function* forEachInterpolationSegment(
9094
ts: typeof import('typescript'),
95+
template: Sfc['template'],
9196
destructuredPropNames: Set<string> | undefined,
9297
templateRefNames: Set<string> | undefined,
9398
ctx: TemplateCodegenContext,
9499
originalCode: string,
95100
start: number | undefined,
96-
astHolder: any,
97101
prefix: string,
98102
suffix: string,
99103
): Generator<Segment> {
@@ -108,7 +112,7 @@ function* forEachInterpolationSegment(
108112
});
109113
}
110114
else {
111-
const ast = createTsAst(ts, astHolder, code);
115+
const ast = createTsAst(ts, template?.ast, code);
112116
const varCb = (id: ts.Identifier, isShorthand: boolean) => {
113117
const text = getNodeText(ts, id, ast);
114118
if (!shouldIdentifierSkipped(ctx, text, destructuredPropNames)) {

packages/language-core/lib/codegen/template/objectProperty.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ export function* generateObjectProperty(
1414
code: string,
1515
offset: number,
1616
features: VueCodeInformation,
17-
astHolder?: any,
1817
shouldCamelize = false,
1918
shouldBeConstant = false,
2019
): Generator<Code> {
21-
if (code.startsWith('[') && code.endsWith(']') && astHolder) {
20+
if (code.startsWith('[') && code.endsWith(']')) {
2221
if (shouldBeConstant) {
2322
yield* generateInterpolation(
2423
options,
@@ -27,7 +26,6 @@ export function* generateObjectProperty(
2726
features,
2827
code.slice(1, -1),
2928
offset + 1,
30-
astHolder,
3129
`[__VLS_tryAsConstant(`,
3230
`)]`,
3331
);
@@ -40,7 +38,6 @@ export function* generateObjectProperty(
4038
features,
4139
code,
4240
offset,
43-
astHolder,
4441
);
4542
}
4643
}

packages/language-core/lib/codegen/template/propertyAccess.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export function* generatePropertyAccess(
1111
code: string,
1212
offset?: number,
1313
features?: VueCodeInformation,
14-
astHolder?: any,
1514
): Generator<Code> {
1615
if (!options.compilerOptions.noPropertyAccessFromIndexSignature && identifierRegex.test(code)) {
1716
yield `.`;
@@ -27,7 +26,6 @@ export function* generatePropertyAccess(
2726
features,
2827
code,
2928
offset,
30-
astHolder,
3129
);
3230
}
3331
else {

packages/language-core/lib/codegen/template/slotOutlet.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ export function* generateSlotOutlet(
150150
ctx.codeFeatures.all,
151151
nameProp.exp.content,
152152
nameProp.exp.loc.start.offset,
153-
nameProp.exp,
154153
);
155154
yield `)${endOfLine}`;
156155
ctx.dynamicSlots.push({

packages/language-core/lib/codegen/template/templateChild.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ export function* generateTemplateChild(
101101
ctx.codeFeatures.all,
102102
content,
103103
start,
104-
node.content.loc,
105104
`(`,
106105
`)${endOfLine}`,
107106
);

packages/language-core/lib/codegen/template/vFor.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function* generateVFor(
1717

1818
yield `for (const [`;
1919
if (leftExpressionRange && leftExpressionText) {
20-
const collectAst = createTsAst(options.ts, node.parseResult, `const [${leftExpressionText}]`);
20+
const collectAst = createTsAst(options.ts, options.template.ast, `const [${leftExpressionText}]`);
2121
collectVars(options.ts, collectAst, collectAst, forBlockVars);
2222
yield [
2323
leftExpressionText,
@@ -36,7 +36,6 @@ export function* generateVFor(
3636
ctx.codeFeatures.all,
3737
source.content,
3838
source.loc.start.offset,
39-
source.loc,
4039
`(`,
4140
`)`,
4241
);
@@ -74,7 +73,6 @@ export function* generateVFor(
7473
ctx.codeFeatures.all,
7574
prop.value.content,
7675
prop.value.loc.start.offset,
77-
prop.value.loc,
7876
`(`,
7977
`)`,
8078
);

packages/language-core/lib/codegen/template/vIf.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export function* generateVIf(
3939
ctx.codeFeatures.all,
4040
branch.condition.content,
4141
branch.condition.loc.start.offset,
42-
branch.condition.loc,
4342
`(`,
4443
`)`,
4544
)];

packages/language-core/lib/codegen/template/vSlot.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export function* generateVSlot(
3737
slotDir.arg.loc.source,
3838
slotDir.arg.loc.start.offset,
3939
slotDir.arg.isStatic ? ctx.codeFeatures.withoutHighlight : ctx.codeFeatures.all,
40-
slotDir.arg.loc,
4140
false,
4241
true,
4342
);
@@ -65,7 +64,7 @@ export function* generateVSlot(
6564
}
6665

6766
if (slotDir?.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
68-
const slotAst = createTsAst(options.ts, slotDir, `(${slotDir.exp.content}) => {}`);
67+
const slotAst = createTsAst(options.ts, options.template.ast, `(${slotDir.exp.content}) => {}`);
6968
collectVars(options.ts, slotAst, slotAst, slotBlockVars);
7069
yield* generateSlotParameters(options, ctx, slotAst, slotDir.exp, slotVar);
7170
}

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,19 @@ export function normalizeAttributeValue(node: CompilerDOM.TextNode): [string, nu
6666
return [content, offset];
6767
}
6868

69-
export function createTsAst(ts: typeof import('typescript'), astHolder: any, text: string) {
70-
if (astHolder.__volar_ast_text !== text) {
71-
astHolder.__volar_ast_text = text;
72-
astHolder.__volar_ast = ts.createSourceFile('/a.ts', text, 99 satisfies ts.ScriptTarget.ESNext);
69+
export function createTsAst(
70+
ts: typeof import('typescript'),
71+
templateAst: CompilerDOM.RootNode | undefined,
72+
text: string,
73+
) {
74+
const inlineTsAsts = (templateAst as any)?.__volar_inlineTsAsts;
75+
let ast = inlineTsAsts?.get(text);
76+
if (!ast) {
77+
ast = ts.createSourceFile('/a.ts', text, 99 satisfies ts.ScriptTarget.ESNext);
78+
inlineTsAsts?.set(text, ast);
7379
}
74-
return astHolder.__volar_ast as ts.SourceFile;
80+
ast.__volar_used = true;
81+
return ast as ts.SourceFile;
7582
}
7683

7784
export function generateSfcBlockSection(block: SfcBlock, start: number, end: number, features: VueCodeInformation): Code {

packages/language-core/lib/plugins/vue-template-inline-ts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ const plugin: VueLanguagePlugin = ctx => {
107107
&& prop.exp.constType !== CompilerDOM.ConstantTypes.CAN_STRINGIFY // style='z-index: 2' will compile to {'z-index':'2'}
108108
) {
109109
if (prop.name === 'on' && prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
110-
const ast = createTsAst(ctx.modules.typescript, prop.exp, prop.exp.content);
110+
const ast = createTsAst(ctx.modules.typescript, sfc.template!.ast, prop.exp.content);
111111
if (isCompoundExpression(ctx.modules.typescript, ast)) {
112112
addFormatCodes(
113113
prop.exp.loc.source,

0 commit comments

Comments
 (0)