Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(language-core): type support of v-model modifiers #5061

Merged
merged 11 commits into from
Dec 17, 2024
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