Skip to content

Commit 06b98f5

Browse files
authored
feat(language-core): type support of v-model modifiers (#5061)
1 parent d34ea59 commit 06b98f5

File tree

11 files changed

+201
-133
lines changed

11 files changed

+201
-133
lines changed

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

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -393,22 +393,25 @@ function* generateComponentProps(
393393
if (scriptSetupRanges.defineProp.length) {
394394
yield `const __VLS_defaults = {${newLine}`;
395395
for (const defineProp of scriptSetupRanges.defineProp) {
396-
if (defineProp.defaultValue) {
397-
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);
398-
399-
if (defineProp.name || defineProp.isModel) {
400-
yield propName!;
401-
}
402-
else if (defineProp.localName) {
403-
yield localName!;
404-
}
405-
else {
406-
continue;
407-
}
408-
yield `: `;
409-
yield getRangeName(scriptSetup, defineProp.defaultValue);
410-
yield `,${newLine}`;
396+
if (!defineProp.defaultValue) {
397+
continue;
398+
}
399+
400+
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);
401+
402+
if (defineProp.name || defineProp.isModel) {
403+
yield `'${propName}'`;
404+
}
405+
else if (defineProp.localName) {
406+
yield localName!;
411407
}
408+
else {
409+
continue;
410+
}
411+
412+
yield `: `;
413+
yield getRangeName(scriptSetup, defineProp.defaultValue);
414+
yield `,${newLine}`;
412415
}
413416
yield `}${endOfLine}`;
414417
}
@@ -450,12 +453,9 @@ function* generateComponentProps(
450453
yield `,${newLine}`;
451454

452455
if (defineProp.modifierType) {
453-
let modifierName = `modelModifiers`;
454-
if (defineProp.name) {
455-
modifierName = `${getRangeName(scriptSetup, defineProp.name, true)}Modifiers`;
456-
}
456+
const modifierName = `${defineProp.name ? propName : 'model'}Modifiers`;
457457
const modifierType = getRangeName(scriptSetup, defineProp.modifierType);
458-
yield `${modifierName}?: Partial<Record<${modifierType}, true>>,${newLine}`;
458+
yield `'${modifierName}'?: Partial<Record<${modifierType}, true>>,${newLine}`;
459459
}
460460
}
461461
yield `}`;
@@ -529,14 +529,12 @@ function getPropAndLocalName(
529529
if (defineProp.name) {
530530
propName = propName!.replace(/['"]+/g, '');
531531
}
532-
return [propName, localName];
532+
return [propName, localName] as const;
533533
}
534534

535535
function getRangeName(
536536
scriptSetup: NonNullable<Sfc['scriptSetup']>,
537-
range: TextRange,
538-
unwrap = false
537+
range: TextRange
539538
) {
540-
const offset = unwrap ? 1 : 0;
541-
return scriptSetup.content.slice(range.start + offset, range.end - offset);
542-
}
539+
return scriptSetup.content.slice(range.start, range.end);
540+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ const _codeFeatures = {
3838
navigation: true,
3939
completion: { isAdditional: true },
4040
} as VueCodeInformation,
41+
withoutNavigation: {
42+
verification: true,
43+
completion: true,
44+
semantic: true,
45+
} as VueCodeInformation,
4146
withoutHighlight: {
4247
semantic: { shouldHighlight: () => false },
4348
verification: true,

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ export function* generateComponent(
200200
}
201201

202202
yield `// @ts-ignore${newLine}`;
203-
yield `const ${var_functionalComponent} = __VLS_asFunctionalComponent(${var_originalComponent}, new ${var_originalComponent}({`;
203+
yield `const ${var_functionalComponent} = __VLS_asFunctionalComponent(${var_originalComponent}, new ${var_originalComponent}({${newLine}`;
204204
yield* generateElementProps(options, ctx, node, props, options.vueCompilerOptions.strictTemplates, false);
205205
yield `}))${endOfLine}`;
206206

@@ -211,7 +211,7 @@ export function* generateComponent(
211211
startTagOffset,
212212
startTagOffset + node.tag.length,
213213
ctx.codeFeatures.verification,
214-
`{`,
214+
`{${newLine}`,
215215
...generateElementProps(options, ctx, node, props, options.vueCompilerOptions.strictTemplates, true, failedPropExps),
216216
`}`
217217
);
@@ -314,7 +314,7 @@ export function* generateElement(
314314
startTagOffset,
315315
startTagOffset + node.tag.length,
316316
ctx.codeFeatures.verification,
317-
`{`,
317+
`{${newLine}`,
318318
...generateElementProps(options, ctx, node, node.props, options.vueCompilerOptions.strictTemplates, true, failedPropExps),
319319
`}`
320320
);

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

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function* generateElementDirectives(
3939
...generateArg(options, ctx, prop),
4040
...generateModifiers(options, ctx, prop),
4141
...generateValue(options, ctx, prop),
42-
`}, null!, null!)`
42+
` }, null!, null!)`
4343
);
4444
yield endOfLine;
4545
}
@@ -90,14 +90,14 @@ function* generateArg(
9090
startOffset,
9191
startOffset + arg.content.length,
9292
ctx.codeFeatures.verification,
93-
'arg'
93+
`arg`
9494
);
95-
yield ': ';
95+
yield `: `;
9696
if (arg.isStatic) {
9797
yield* generateStringLiteralKey(
9898
arg.content,
9999
startOffset,
100-
ctx.codeFeatures.withoutHighlight
100+
ctx.codeFeatures.all
101101
);
102102
}
103103
else {
@@ -109,66 +109,78 @@ function* generateArg(
109109
arg.content,
110110
startOffset,
111111
arg.loc,
112-
'(',
113-
')'
112+
`(`,
113+
`)`
114114
);
115115
}
116-
yield ', ';
116+
yield `, `;
117117
}
118118

119-
function* generateModifiers(
119+
export function* generateModifiers(
120120
options: TemplateCodegenOptions,
121121
ctx: TemplateCodegenContext,
122-
prop: CompilerDOM.DirectiveNode
122+
prop: CompilerDOM.DirectiveNode,
123+
propertyName: string = 'modifiers'
123124
): Generator<Code> {
124-
if (options.vueCompilerOptions.target < 3.5) {
125+
const { modifiers } = prop;
126+
if (!modifiers.length) {
125127
return;
126128
}
127129

128-
yield 'modifiers: { ';
129-
for (const mod of prop.modifiers) {
130+
const startOffset = modifiers[0].loc.start.offset - 1;
131+
const endOffset = modifiers.at(-1)!.loc.end.offset;
132+
133+
yield* wrapWith(
134+
startOffset,
135+
endOffset,
136+
ctx.codeFeatures.verification,
137+
propertyName
138+
);
139+
yield `: { `;
140+
for (const mod of modifiers) {
130141
yield* generateObjectProperty(
131142
options,
132143
ctx,
133144
mod.content,
134145
mod.loc.start.offset,
135-
ctx.codeFeatures.withoutHighlight
146+
ctx.codeFeatures.withoutNavigation
136147
);
137-
yield ': true, ';
148+
yield `: true, `;
138149
}
139-
yield '}, ';
150+
yield `}, `;
140151
}
141152

142153
function* generateValue(
143154
options: TemplateCodegenOptions,
144155
ctx: TemplateCodegenContext,
145156
prop: CompilerDOM.DirectiveNode
146157
): Generator<Code> {
147-
if (prop.exp?.type !== CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
158+
const { exp } = prop;
159+
if (exp?.type !== CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
148160
return;
149161
}
150162

151163
yield* wrapWith(
152-
prop.exp.loc.start.offset,
153-
prop.exp.loc.end.offset,
164+
exp.loc.start.offset,
165+
exp.loc.end.offset,
154166
ctx.codeFeatures.verification,
155-
'value'
167+
`value`
156168
);
157-
yield ': ';
169+
yield `: `;
158170
yield* wrapWith(
159-
prop.exp.loc.start.offset,
160-
prop.exp.loc.end.offset,
171+
exp.loc.start.offset,
172+
exp.loc.end.offset,
161173
ctx.codeFeatures.verification,
162174
...generateInterpolation(
163175
options,
164176
ctx,
165177
'template',
166178
ctx.codeFeatures.all,
167-
prop.exp.content,
168-
prop.exp.loc.start.offset,
169-
prop.exp.loc,
170-
'(',
171-
')'
179+
exp.content,
180+
exp.loc.start.offset,
181+
exp.loc,
182+
`(`,
183+
`)`
172184
)
173185
);
174186
}

0 commit comments

Comments
 (0)