Skip to content

Commit

Permalink
feat(language-core): type support of v-model modifiers (#5061)
Browse files Browse the repository at this point in the history
  • Loading branch information
KazariEX authored Dec 17, 2024
1 parent d34ea59 commit 06b98f5
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 133 deletions.
50 changes: 24 additions & 26 deletions packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,22 +393,25 @@ function* generateComponentProps(
if (scriptSetupRanges.defineProp.length) {
yield `const __VLS_defaults = {${newLine}`;
for (const defineProp of scriptSetupRanges.defineProp) {
if (defineProp.defaultValue) {
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);

if (defineProp.name || defineProp.isModel) {
yield propName!;
}
else if (defineProp.localName) {
yield localName!;
}
else {
continue;
}
yield `: `;
yield getRangeName(scriptSetup, defineProp.defaultValue);
yield `,${newLine}`;
if (!defineProp.defaultValue) {
continue;
}

const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);

if (defineProp.name || defineProp.isModel) {
yield `'${propName}'`;
}
else if (defineProp.localName) {
yield localName!;
}
else {
continue;
}

yield `: `;
yield getRangeName(scriptSetup, defineProp.defaultValue);
yield `,${newLine}`;
}
yield `}${endOfLine}`;
}
Expand Down Expand Up @@ -450,12 +453,9 @@ function* generateComponentProps(
yield `,${newLine}`;

if (defineProp.modifierType) {
let modifierName = `modelModifiers`;
if (defineProp.name) {
modifierName = `${getRangeName(scriptSetup, defineProp.name, true)}Modifiers`;
}
const modifierName = `${defineProp.name ? propName : 'model'}Modifiers`;
const modifierType = getRangeName(scriptSetup, defineProp.modifierType);
yield `${modifierName}?: Partial<Record<${modifierType}, true>>,${newLine}`;
yield `'${modifierName}'?: Partial<Record<${modifierType}, true>>,${newLine}`;
}
}
yield `}`;
Expand Down Expand Up @@ -529,14 +529,12 @@ function getPropAndLocalName(
if (defineProp.name) {
propName = propName!.replace(/['"]+/g, '');
}
return [propName, localName];
return [propName, localName] as const;
}

function getRangeName(
scriptSetup: NonNullable<Sfc['scriptSetup']>,
range: TextRange,
unwrap = false
range: TextRange
) {
const offset = unwrap ? 1 : 0;
return scriptSetup.content.slice(range.start + offset, range.end - offset);
}
return scriptSetup.content.slice(range.start, range.end);
}
5 changes: 5 additions & 0 deletions packages/language-core/lib/codegen/template/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ const _codeFeatures = {
navigation: true,
completion: { isAdditional: true },
} as VueCodeInformation,
withoutNavigation: {
verification: true,
completion: true,
semantic: true,
} as VueCodeInformation,
withoutHighlight: {
semantic: { shouldHighlight: () => false },
verification: true,
Expand Down
6 changes: 3 additions & 3 deletions packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export function* generateComponent(
}

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

Expand All @@ -211,7 +211,7 @@ export function* generateComponent(
startTagOffset,
startTagOffset + node.tag.length,
ctx.codeFeatures.verification,
`{`,
`{${newLine}`,
...generateElementProps(options, ctx, node, props, options.vueCompilerOptions.strictTemplates, true, failedPropExps),
`}`
);
Expand Down Expand Up @@ -314,7 +314,7 @@ export function* generateElement(
startTagOffset,
startTagOffset + node.tag.length,
ctx.codeFeatures.verification,
`{`,
`{${newLine}`,
...generateElementProps(options, ctx, node, node.props, options.vueCompilerOptions.strictTemplates, true, failedPropExps),
`}`
);
Expand Down
66 changes: 39 additions & 27 deletions packages/language-core/lib/codegen/template/elementDirectives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function* generateElementDirectives(
...generateArg(options, ctx, prop),
...generateModifiers(options, ctx, prop),
...generateValue(options, ctx, prop),
`}, null!, null!)`
` }, null!, null!)`
);
yield endOfLine;
}
Expand Down Expand Up @@ -90,14 +90,14 @@ function* generateArg(
startOffset,
startOffset + arg.content.length,
ctx.codeFeatures.verification,
'arg'
`arg`
);
yield ': ';
yield `: `;
if (arg.isStatic) {
yield* generateStringLiteralKey(
arg.content,
startOffset,
ctx.codeFeatures.withoutHighlight
ctx.codeFeatures.all
);
}
else {
Expand All @@ -109,66 +109,78 @@ function* generateArg(
arg.content,
startOffset,
arg.loc,
'(',
')'
`(`,
`)`
);
}
yield ', ';
yield `, `;
}

function* generateModifiers(
export function* generateModifiers(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
prop: CompilerDOM.DirectiveNode
prop: CompilerDOM.DirectiveNode,
propertyName: string = 'modifiers'
): Generator<Code> {
if (options.vueCompilerOptions.target < 3.5) {
const { modifiers } = prop;
if (!modifiers.length) {
return;
}

yield 'modifiers: { ';
for (const mod of prop.modifiers) {
const startOffset = modifiers[0].loc.start.offset - 1;
const endOffset = modifiers.at(-1)!.loc.end.offset;

yield* wrapWith(
startOffset,
endOffset,
ctx.codeFeatures.verification,
propertyName
);
yield `: { `;
for (const mod of modifiers) {
yield* generateObjectProperty(
options,
ctx,
mod.content,
mod.loc.start.offset,
ctx.codeFeatures.withoutHighlight
ctx.codeFeatures.withoutNavigation
);
yield ': true, ';
yield `: true, `;
}
yield '}, ';
yield `}, `;
}

function* generateValue(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
prop: CompilerDOM.DirectiveNode
): Generator<Code> {
if (prop.exp?.type !== CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const { exp } = prop;
if (exp?.type !== CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
return;
}

yield* wrapWith(
prop.exp.loc.start.offset,
prop.exp.loc.end.offset,
exp.loc.start.offset,
exp.loc.end.offset,
ctx.codeFeatures.verification,
'value'
`value`
);
yield ': ';
yield `: `;
yield* wrapWith(
prop.exp.loc.start.offset,
prop.exp.loc.end.offset,
exp.loc.start.offset,
exp.loc.end.offset,
ctx.codeFeatures.verification,
...generateInterpolation(
options,
ctx,
'template',
ctx.codeFeatures.all,
prop.exp.content,
prop.exp.loc.start.offset,
prop.exp.loc,
'(',
')'
exp.content,
exp.loc.start.offset,
exp.loc,
`(`,
`)`
)
);
}
Expand Down
Loading

0 comments on commit 06b98f5

Please sign in to comment.