{
- yield* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, inheritAttrs);
- yield* generateEmitsOption(options, scriptSetup, scriptSetupRanges);
-}
-
-export function* generatePropsOption(
- options: ScriptCodegenOptions,
- ctx: ScriptCodegenContext,
- scriptSetup: NonNullable,
- scriptSetupRanges: ScriptSetupRanges,
- inheritAttrs: boolean
-) {
+ const emitOptionCodes = [...generateEmitsOption(options, scriptSetup, scriptSetupRanges)];
+ for (const code of emitOptionCodes) {
+ yield code;
+ }
if (options.vueCompilerOptions.target >= 3.5) {
const types = [];
- if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
- types.push(`ReturnType['attrs']`);
+ if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !emitOptionCodes.length) {
+ types.push(`{} as ReturnType['attrs']`);
}
if (ctx.generatedPropsType) {
types.push(`{} as __VLS_PublicProps`);
}
- if (types.length) {
- yield `__typeProps: ${types.join(' & ')},${newLine}`;
+ if (types.length === 1) {
+ yield `__typeProps: ${types[0]},${newLine}`;
+ }
+ else if (types.length >= 2) {
+ yield `__typeProps: {${newLine}`;
+ for (const type of types) {
+ yield `...${type},${newLine}`;
+ }
+ yield `},${newLine}`;
}
}
if (options.vueCompilerOptions.target < 3.5 || !ctx.generatedPropsType || scriptSetupRanges.props.withDefaults) {
const codegens: (() => Generator)[] = [];
- if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
+ if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !emitOptionCodes.length) {
codegens.push(function* () {
yield `{} as ${ctx.helperTypes.TypePropsToOption.name}<__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}['attrs']>, {}>>`;
});
@@ -148,25 +148,63 @@ export function* generateEmitsOption(
scriptSetup: NonNullable,
scriptSetupRanges: ScriptSetupRanges
): Generator {
- if (!scriptSetupRanges.emits.define && !scriptSetupRanges.defineProp.some(p => p.isModel)) {
- return;
+ const codes: {
+ optionExp?: Code[],
+ typeOptionType?: Code[],
+ }[] = [];
+ if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
+ codes.push({
+ optionExp: [`{} as __VLS_NormalizeEmits<__VLS_ModelEmitsType>`],
+ typeOptionType: [`__VLS_ModelEmitsType`],
+ });
}
-
- if (options.vueCompilerOptions.target < 3.5 || scriptSetupRanges.emits.define?.arg || scriptSetupRanges.emits.define?.hasUnionTypeArg) {
- yield `emits: ({} as __VLS_NormalizeEmits<__VLS_ModelEmitsType`;
- if (scriptSetupRanges?.emits.define) {
- yield ` & typeof `;
- yield scriptSetupRanges.emits.name ?? '__VLS_emit';
+ if (scriptSetupRanges.emits.define) {
+ const { typeArg, hasUnionTypeArg } = scriptSetupRanges.emits.define;
+ codes.push({
+ optionExp: [`{} as __VLS_NormalizeEmits`],
+ typeOptionType: typeArg && !hasUnionTypeArg ? [scriptSetup.content.slice(typeArg.start, typeArg.end)] : undefined,
+ });
+ }
+ if (options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionType)) {
+ if (codes.length === 1) {
+ yield `__typeEmits: {} as `;
+ for (const code of codes[0].typeOptionType!) {
+ yield code;
+ }
+ yield `,${newLine}`;
+ }
+ else if (codes.length >= 2) {
+ yield `__typeEmits: {} as `;
+ for (const code of codes[0].typeOptionType!) {
+ yield code;
+ }
+ for (let i = 1; i < codes.length; i++) {
+ yield ` & `;
+ for (const code of codes[i].typeOptionType!) {
+ yield code;
+ }
+ }
+ yield `,${newLine}`;
}
- yield `>),${newLine}`;
}
- else {
- yield `__typeEmits: {} as __VLS_ModelEmitsType`;
- const typeArg = scriptSetupRanges.emits.define?.typeArg;
- if (typeArg) {
- yield ` & `;
- yield scriptSetup.content.slice(typeArg.start, typeArg.end);
+ else if (codes.every(code => code.optionExp)) {
+ if (codes.length === 1) {
+ yield `emits: `;
+ for (const code of codes[0].optionExp!) {
+ yield code;
+ }
+ yield `,${newLine}`;
+ }
+ else if (codes.length >= 2) {
+ yield `emits: {${newLine}`;
+ for (const code of codes) {
+ yield `...`;
+ for (const c of code.optionExp!) {
+ yield c;
+ }
+ yield `,${newLine}`;
+ }
+ yield `},${newLine}`;
}
- yield `,${newLine}`;
}
}
diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts
index 869a9b60ed..05bab1100f 100644
--- a/packages/language-core/lib/codegen/script/scriptSetup.ts
+++ b/packages/language-core/lib/codegen/script/scriptSetup.ts
@@ -303,14 +303,16 @@ function* generateComponentProps(
scriptSetupRanges: ScriptSetupRanges,
definePropMirrors: Map
): Generator {
- yield `const __VLS_fnComponent = `
- + `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
+ yield `const __VLS_fnComponent = (await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
+
if (scriptSetupRanges.props.define?.arg) {
- yield ` props: `;
+ yield `props: `;
yield generateSfcBlockSection(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, codeFeatures.navigation);
yield `,${newLine}`;
}
+
yield* generateEmitsOption(options, scriptSetup, scriptSetupRanges);
+
yield `})${endOfLine}`;
yield `type __VLS_BuiltInPublicProps = ${options.vueCompilerOptions.target >= 3.4
@@ -418,32 +420,31 @@ function* generateModelEmits(
scriptSetup: NonNullable,
scriptSetupRanges: ScriptSetupRanges
): Generator {
- yield `type __VLS_ModelEmitsType = `;
- if (scriptSetupRanges.defineProp.filter(p => p.isModel).length) {
- if (options.vueCompilerOptions.target < 3.5) {
- yield `typeof __VLS_modelEmitsType${endOfLine}`;
- yield `const __VLS_modelEmitsType = (await import('${options.vueCompilerOptions.lib}')).defineEmits<`;
- }
- yield `{${newLine}`;
- for (const defineProp of scriptSetupRanges.defineProp) {
- if (!defineProp.isModel) {
- continue;
+ const defineModels = scriptSetupRanges.defineProp.filter(p => p.isModel);
+ if (defineModels.length) {
+ const generateDefineModels = function* () {
+ for (const defineModel of defineModels) {
+ const [propName, localName] = getPropAndLocalName(scriptSetup, defineModel);
+ yield `'update:${propName}': [${propName}:`;
+ yield* generateDefinePropType(scriptSetup, propName, localName, defineModel);
+ yield `]${endOfLine}`;
}
-
- const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp);
-
- yield `'update:${propName}': [${propName}:`;
- yield* generateDefinePropType(scriptSetup, propName, localName, defineProp);
- yield `]${endOfLine}`;
+ };
+ if (options.vueCompilerOptions.target >= 3.5) {
+ yield `type __VLS_ModelEmitsType = {${newLine}`;
+ yield* generateDefineModels();
+ yield `}${endOfLine}`;
}
- yield `}`;
- if (options.vueCompilerOptions.target < 3.5) {
- yield `>()`;
+ else {
+ yield `const __VLS_modelEmitsType = (await import('${options.vueCompilerOptions.lib}')).defineEmits<{${newLine}`;
+ yield* generateDefineModels();
+ yield `}>()${endOfLine}`;
+ yield `type __VLS_ModelEmitsType = typeof __VLS_modelEmitsType${endOfLine}`;
}
- } else {
- yield `{}`;
}
- yield endOfLine;
+ else {
+ yield `type __VLS_ModelEmitsType = {}${endOfLine}`;
+ }
}
function* generateStyleModules(
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/basic.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/basic.vue
new file mode 100644
index 0000000000..e7574c27d2
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/basic.vue
@@ -0,0 +1,12 @@
+
+
+
+ exactType(v, {} as string)" />
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/child.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/child.vue
new file mode 100644
index 0000000000..57e78c68eb
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/child.vue
@@ -0,0 +1,5 @@
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/main.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/main.vue
new file mode 100644
index 0000000000..247181ad3c
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/main.vue
@@ -0,0 +1,8 @@
+
+
+
+ exactType(v, {} as number)" />
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/basic.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/basic.vue
new file mode 100644
index 0000000000..f24d7f587a
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/basic.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProps/child.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/child.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProps/child.vue
rename to test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/child.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/main.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/main.vue
new file mode 100644
index 0000000000..23c4cd71d8
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/main.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProps/basic.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProps/basic.vue
rename to test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/child.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/child.vue
new file mode 100644
index 0000000000..74e63d8179
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/child.vue
@@ -0,0 +1,5 @@
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProps/main.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProps/main.vue
rename to test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/main.vue
From 5a9bb123daa1481d196fc812de77ef1bfa1baad5 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Tue, 27 Aug 2024 00:26:03 +0800
Subject: [PATCH 04/93] refactor(language-core): rewrite generatePropsOption
---
.../lib/codegen/script/component.ts | 201 ++++++++----------
.../lib/codegen/script/internalComponent.ts | 17 +-
.../lib/codegen/script/scriptSetup.ts | 12 +-
.../tsc/tests/__snapshots__/dts.spec.ts.snap | 2 +-
4 files changed, 106 insertions(+), 126 deletions(-)
diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts
index f1618c3f59..ca7cf0b44d 100644
--- a/packages/language-core/lib/codegen/script/component.ts
+++ b/packages/language-core/lib/codegen/script/component.ts
@@ -1,4 +1,3 @@
-import type { ScriptRanges } from '../../parsers/scriptRanges';
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges';
import type { Code, Sfc } from '../../types';
import { endOfLine, generateSfcBlockSection, newLine } from '../common';
@@ -31,10 +30,15 @@ export function* generateComponent(
yield `}${endOfLine}`;
yield `},${newLine}`;
if (!ctx.bypassDefineComponent) {
- yield* generateScriptSetupOptions(options, ctx, scriptSetup, scriptSetupRanges, true);
+ const emitOptionCodes = [...generateEmitsOption(options, scriptSetup, scriptSetupRanges)];
+ for (const code of emitOptionCodes) {
+ yield code;
+ }
+ yield* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, !!emitOptionCodes.length, true);
}
- if (options.sfc.script && options.scriptRanges) {
- yield* generateScriptOptions(options.sfc.script, options.scriptRanges);
+ if (options.sfc.script && options.scriptRanges?.exportDefault?.args) {
+ const { args } = options.scriptRanges.exportDefault;
+ yield generateSfcBlockSection(options.sfc.script, args.start + 1, args.end - 1, codeFeatures.all);
}
if (options.vueCompilerOptions.target >= 3.5 && scriptSetupRanges.templateRefs.length) {
yield `__typeRefs: {} as __VLS_Refs,${newLine}`;
@@ -55,134 +59,42 @@ export function* generateComponentSetupReturns(scriptSetupRanges: ScriptSetupRan
}
}
-export function* generateScriptOptions(
- script: NonNullable,
- scriptRanges: ScriptRanges
-): Generator {
- if (scriptRanges.exportDefault?.args) {
- yield generateSfcBlockSection(script, scriptRanges.exportDefault.args.start + 1, scriptRanges.exportDefault.args.end - 1, codeFeatures.all);
- }
-}
-
-export function* generateScriptSetupOptions(
- options: ScriptCodegenOptions,
- ctx: ScriptCodegenContext,
- scriptSetup: NonNullable,
- scriptSetupRanges: ScriptSetupRanges,
- inheritAttrs: boolean
-): Generator {
- const emitOptionCodes = [...generateEmitsOption(options, scriptSetup, scriptSetupRanges)];
- for (const code of emitOptionCodes) {
- yield code;
- }
-
- if (options.vueCompilerOptions.target >= 3.5) {
- const types = [];
- if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !emitOptionCodes.length) {
- types.push(`{} as ReturnType['attrs']`);
- }
- if (ctx.generatedPropsType) {
- types.push(`{} as __VLS_PublicProps`);
- }
- if (types.length === 1) {
- yield `__typeProps: ${types[0]},${newLine}`;
- }
- else if (types.length >= 2) {
- yield `__typeProps: {${newLine}`;
- for (const type of types) {
- yield `...${type},${newLine}`;
- }
- yield `},${newLine}`;
- }
- }
- if (options.vueCompilerOptions.target < 3.5 || !ctx.generatedPropsType || scriptSetupRanges.props.withDefaults) {
- const codegens: (() => Generator)[] = [];
-
- if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !emitOptionCodes.length) {
- codegens.push(function* () {
- yield `{} as ${ctx.helperTypes.TypePropsToOption.name}<__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}['attrs']>, {}>>`;
- });
- }
-
- if (ctx.generatedPropsType) {
- codegens.push(function* () {
- yield `{} as `;
- if (scriptSetupRanges.props.withDefaults?.arg) {
- yield `${ctx.helperTypes.WithDefaults.name}<`;
- }
- yield `${ctx.helperTypes.TypePropsToOption.name}<`;
- yield `__VLS_PublicProps>`;
- if (scriptSetupRanges.props.withDefaults?.arg) {
- yield `, typeof __VLS_withDefaultsArg>`;
- }
- });
- }
- if (scriptSetupRanges.props.define?.arg) {
- const { arg } = scriptSetupRanges.props.define;
- codegens.push(function* () {
- yield generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation);
- });
- }
-
- if (codegens.length === 1) {
- yield `props: `;
- for (const generate of codegens) {
- yield* generate();
- }
- yield `,${newLine}`;
- }
- else if (codegens.length >= 2) {
- yield `props: {${newLine}`;
- for (const generate of codegens) {
- yield `...`;
- yield* generate();
- yield `,${newLine}`;
- }
- yield `},${newLine}`;
- }
- }
-}
-
export function* generateEmitsOption(
options: ScriptCodegenOptions,
scriptSetup: NonNullable,
scriptSetupRanges: ScriptSetupRanges
): Generator {
const codes: {
- optionExp?: Code[],
- typeOptionType?: Code[],
+ optionExp?: Code,
+ typeOptionType?: Code,
}[] = [];
if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
codes.push({
- optionExp: [`{} as __VLS_NormalizeEmits<__VLS_ModelEmitsType>`],
- typeOptionType: [`__VLS_ModelEmitsType`],
+ optionExp: `{} as __VLS_NormalizeEmits<__VLS_ModelEmitsType>`,
+ typeOptionType: `__VLS_ModelEmitsType`,
});
}
if (scriptSetupRanges.emits.define) {
const { typeArg, hasUnionTypeArg } = scriptSetupRanges.emits.define;
codes.push({
- optionExp: [`{} as __VLS_NormalizeEmits`],
- typeOptionType: typeArg && !hasUnionTypeArg ? [scriptSetup.content.slice(typeArg.start, typeArg.end)] : undefined,
+ optionExp: `{} as __VLS_NormalizeEmits`,
+ typeOptionType: typeArg && !hasUnionTypeArg
+ ? scriptSetup.content.slice(typeArg.start, typeArg.end)
+ : undefined,
});
}
if (options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionType)) {
if (codes.length === 1) {
yield `__typeEmits: {} as `;
- for (const code of codes[0].typeOptionType!) {
- yield code;
- }
+ yield codes[0].typeOptionType!;
yield `,${newLine}`;
}
else if (codes.length >= 2) {
yield `__typeEmits: {} as `;
- for (const code of codes[0].typeOptionType!) {
- yield code;
- }
+ yield codes[0].typeOptionType!;
for (let i = 1; i < codes.length; i++) {
yield ` & `;
- for (const code of codes[i].typeOptionType!) {
- yield code;
- }
+ yield codes[i].typeOptionType!;
}
yield `,${newLine}`;
}
@@ -190,18 +102,81 @@ export function* generateEmitsOption(
else if (codes.every(code => code.optionExp)) {
if (codes.length === 1) {
yield `emits: `;
- for (const code of codes[0].optionExp!) {
- yield code;
- }
+ yield codes[0].optionExp!;
yield `,${newLine}`;
}
else if (codes.length >= 2) {
yield `emits: {${newLine}`;
for (const code of codes) {
yield `...`;
- for (const c of code.optionExp!) {
- yield c;
- }
+ yield code.optionExp!;
+ yield `,${newLine}`;
+ }
+ yield `},${newLine}`;
+ }
+ }
+}
+
+export function* generatePropsOption(
+ options: ScriptCodegenOptions,
+ ctx: ScriptCodegenContext,
+ scriptSetup: NonNullable,
+ scriptSetupRanges: ScriptSetupRanges,
+ hasEmitsOption: boolean,
+ inheritAttrs: boolean
+): Generator {
+ const optionExpCodes: Code[] = [];
+ const typeOptionExpCodes: Code[] = [];
+
+ if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !hasEmitsOption) {
+ optionExpCodes.push(`{} as ${ctx.helperTypes.TypePropsToOption.name}<__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}['attrs']>, {}>>`);
+ typeOptionExpCodes.push(`{} as ReturnType['attrs']`);
+ }
+ if (ctx.generatedPropsType) {
+ optionExpCodes.push([
+ `{} as `,
+ scriptSetupRanges.props.withDefaults?.arg ? `${ctx.helperTypes.WithDefaults.name}<` : '',
+ `${ctx.helperTypes.TypePropsToOption.name}<__VLS_PublicProps>`,
+ scriptSetupRanges.props.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
+ ].join(''));
+ typeOptionExpCodes.push(`{} as __VLS_PublicProps`);
+ }
+
+ if (scriptSetupRanges.props.define?.arg) {
+ const { arg } = scriptSetupRanges.props.define;
+ optionExpCodes.push(generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation));
+ }
+
+ const useTypeOption = options.vueCompilerOptions.target >= 3.5 && typeOptionExpCodes.length;
+ const useOption = (!useTypeOption || scriptSetupRanges.props.withDefaults) && optionExpCodes.length;
+
+ if (useTypeOption) {
+ if (typeOptionExpCodes.length === 1) {
+ yield `__typeProps: `;
+ yield typeOptionExpCodes[0];
+ yield `,${newLine}`;
+ }
+ else if (typeOptionExpCodes.length >= 2) {
+ yield `__typeProps: {${newLine}`;
+ for (const code of typeOptionExpCodes) {
+ yield `...`;
+ yield code;
+ yield `,${newLine}`;
+ }
+ yield `},${newLine}`;
+ }
+ }
+ if (useOption) {
+ if (optionExpCodes.length === 1) {
+ yield `props: `;
+ yield optionExpCodes[0];
+ yield `,${newLine}`;
+ }
+ else if (optionExpCodes.length >= 2) {
+ yield `props: {${newLine}`;
+ for (const code of optionExpCodes) {
+ yield `...`;
+ yield code;
yield `,${newLine}`;
}
yield `},${newLine}`;
diff --git a/packages/language-core/lib/codegen/script/internalComponent.ts b/packages/language-core/lib/codegen/script/internalComponent.ts
index af8859709c..4cf91246f7 100644
--- a/packages/language-core/lib/codegen/script/internalComponent.ts
+++ b/packages/language-core/lib/codegen/script/internalComponent.ts
@@ -1,9 +1,9 @@
import type { Code } from '../../types';
-import { endOfLine, newLine } from '../common';
+import { endOfLine, generateSfcBlockSection, newLine } from '../common';
import type { TemplateCodegenContext } from '../template/context';
-import { generateComponentSetupReturns, generateScriptOptions, generateScriptSetupOptions } from './component';
+import { generateComponentSetupReturns, generateEmitsOption, generatePropsOption } from './component';
import type { ScriptCodegenContext } from './context';
-import type { ScriptCodegenOptions } from './index';
+import { codeFeatures, type ScriptCodegenOptions } from './index';
import { getTemplateUsageVars } from './template';
export function* generateInternalComponent(
@@ -52,10 +52,15 @@ export function* generateInternalComponent(
yield `__typeRefs: {} as __VLS_Refs,${newLine}`;
}
if (options.sfc.scriptSetup && options.scriptSetupRanges && !ctx.bypassDefineComponent) {
- yield* generateScriptSetupOptions(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges, false);
+ const emitOptionCodes = [...generateEmitsOption(options, options.sfc.scriptSetup, options.scriptSetupRanges)];
+ for (const code of emitOptionCodes) {
+ yield code;
+ }
+ yield* generatePropsOption(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges, !!emitOptionCodes.length, false);
}
- if (options.sfc.script && options.scriptRanges) {
- yield* generateScriptOptions(options.sfc.script, options.scriptRanges);
+ if (options.sfc.script && options.scriptRanges?.exportDefault?.args) {
+ const { args } = options.scriptRanges.exportDefault;
+ yield generateSfcBlockSection(options.sfc.script, args.start + 1, args.end - 1, codeFeatures.all);
}
yield `})${endOfLine}`; // defineComponent {
}
diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts
index 05bab1100f..6c6c014597 100644
--- a/packages/language-core/lib/codegen/script/scriptSetup.ts
+++ b/packages/language-core/lib/codegen/script/scriptSetup.ts
@@ -57,10 +57,13 @@ export function* generateScriptSetup(
+ ` __VLS_setup = (async () => {${newLine}`;
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, undefined, definePropMirrors);
- const emitTypes = ['__VLS_ModelEmitsType'];
+ const emitTypes: string[] = [];
if (scriptSetupRanges.emits.define) {
- emitTypes.unshift(`typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'}`);
+ emitTypes.push(`typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'}`);
+ }
+ if (scriptSetupRanges.defineProp.some(p => p.isModel)) {
+ emitTypes.push(`__VLS_ModelEmitsType`);
}
yield ` return {} as {${newLine}`
@@ -68,7 +71,7 @@ export function* generateScriptSetup(
+ ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.expose.define ? 'typeof __VLS_exposed' : '{}'}>): void,${newLine}`
+ ` attrs: any,${newLine}`
+ ` slots: __VLS_Slots,${newLine}`
- + ` emit: ${emitTypes.join(' & ')},${newLine}`
+ + ` emit: ${emitTypes.length ? emitTypes.join(' & ') : `{}`},${newLine}`
+ ` }${endOfLine}`;
yield ` })(),${newLine}`; // __VLS_setup = (async () => {
yield `) => ({} as import('${options.vueCompilerOptions.lib}').VNode & { __ctx?: Awaited }))`;
@@ -442,9 +445,6 @@ function* generateModelEmits(
yield `type __VLS_ModelEmitsType = typeof __VLS_modelEmitsType${endOfLine}`;
}
}
- else {
- yield `type __VLS_ModelEmitsType = {}${endOfLine}`;
- }
}
function* generateStyleModules(
diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap
index 4a8769e32e..6a19645cc1 100644
--- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap
+++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap
@@ -78,7 +78,7 @@ exports[`vue-tsc-dts > Input: events/component-generic.vue, Output: events/compo
expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
attrs: any;
slots: {};
- emit: ((evt: "foo", value: string) => void) & {};
+ emit: (evt: "foo", value: string) => void;
}>) => import("vue").VNode & {
From 21205fb9d7c14650c67c2a581cf18f9e7b24bfc4 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Tue, 27 Aug 2024 18:02:51 +0800
Subject: [PATCH 05/93] fix(language-core): fallthrough attributes break
component type when root tag type is unknown (#4729)
---
.../lib/codegen/script/component.ts | 18 +++++++++++++-----
.../vue3/inheritAttrs_unknownTag/basic.vue | 7 +++++++
.../vue3/inheritAttrs_unknownTag/main.vue | 7 +++++++
.../inheritAttrs_unknownTag/basic.vue | 7 +++++++
.../inheritAttrs_unknownTag/main.vue | 7 +++++++
5 files changed, 41 insertions(+), 5 deletions(-)
create mode 100644 test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/basic.vue
create mode 100644 test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/main.vue
create mode 100644 test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/basic.vue
create mode 100644 test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/main.vue
diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts
index ca7cf0b44d..9029d2f1d1 100644
--- a/packages/language-core/lib/codegen/script/component.ts
+++ b/packages/language-core/lib/codegen/script/component.ts
@@ -128,10 +128,6 @@ export function* generatePropsOption(
const optionExpCodes: Code[] = [];
const typeOptionExpCodes: Code[] = [];
- if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !hasEmitsOption) {
- optionExpCodes.push(`{} as ${ctx.helperTypes.TypePropsToOption.name}<__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}['attrs']>, {}>>`);
- typeOptionExpCodes.push(`{} as ReturnType['attrs']`);
- }
if (ctx.generatedPropsType) {
optionExpCodes.push([
`{} as `,
@@ -141,11 +137,23 @@ export function* generatePropsOption(
].join(''));
typeOptionExpCodes.push(`{} as __VLS_PublicProps`);
}
-
if (scriptSetupRanges.props.define?.arg) {
const { arg } = scriptSetupRanges.props.define;
optionExpCodes.push(generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation));
}
+ if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !hasEmitsOption) {
+ const attrsType = `ReturnType['attrs']`;
+ const propsType = `__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}<${attrsType}>, {}>`;
+ const optionType = `${ctx.helperTypes.TypePropsToOption.name}<${propsType}>`;
+ if (optionExpCodes.length) {
+ optionExpCodes.unshift(`{} as ${optionType}`);
+ }
+ else {
+ // workaround for https://github.com/vuejs/core/pull/7419
+ optionExpCodes.unshift(`{} as keyof ${propsType} extends never ? never: ${optionType}`);
+ }
+ typeOptionExpCodes.unshift(`{} as ${attrsType}`);
+ }
const useTypeOption = options.vueCompilerOptions.target >= 3.5 && typeOptionExpCodes.length;
const useOption = (!useTypeOption || scriptSetupRanges.props.withDefaults) && optionExpCodes.length;
diff --git a/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/basic.vue b/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/basic.vue
new file mode 100644
index 0000000000..88fa3d63aa
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/basic.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/main.vue b/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/main.vue
new file mode 100644
index 0000000000..e177ec22aa
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/main.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/basic.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/basic.vue
new file mode 100644
index 0000000000..88fa3d63aa
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/basic.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/main.vue b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/main.vue
new file mode 100644
index 0000000000..e177ec22aa
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/main.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
From d94bd3c9d707fc26ebca5f7da79546b005f17f14 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Tue, 27 Aug 2024 18:52:59 +0800
Subject: [PATCH 06/93] fix(language-core): improve fallthrough attributes and
defineEmit compatibility
---
packages/language-core/lib/codegen/script/component.ts | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts
index 9029d2f1d1..fa49ad1791 100644
--- a/packages/language-core/lib/codegen/script/component.ts
+++ b/packages/language-core/lib/codegen/script/component.ts
@@ -141,8 +141,11 @@ export function* generatePropsOption(
const { arg } = scriptSetupRanges.props.define;
optionExpCodes.push(generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation));
}
- if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size && !hasEmitsOption) {
- const attrsType = `ReturnType['attrs']`;
+ if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
+ let attrsType = `ReturnType['attrs']`;
+ if (hasEmitsOption) {
+ attrsType = `Omit<${attrsType}, \`on\${string}\`>`;
+ }
const propsType = `__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}<${attrsType}>, {}>`;
const optionType = `${ctx.helperTypes.TypePropsToOption.name}<${propsType}>`;
if (optionExpCodes.length) {
From ebb84900b890ddd6b793a8fe78c19d87dc2d7f38 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Tue, 27 Aug 2024 19:13:00 +0800
Subject: [PATCH 07/93] feat(language-core): add fallthroughAttributes compiler
option
---
.../lib/codegen/template/element.ts | 14 +++++++----
packages/language-core/lib/types.ts | 1 +
packages/language-core/lib/utils/ts.ts | 1 +
.../schemas/vue-tsconfig.schema.json | 6 +++++
.../tsc/tests/__snapshots__/dts.spec.ts.snap | 24 +------------------
.../fallthroughAttributes/tsconfig.json | 7 ++++++
.../unknownTag}/basic.vue | 0
.../unknownTag}/main.vue | 0
.../#4699/HelloWorld.vue | 0
.../#4699/main.vue | 0
.../base}/basic.vue | 0
.../base}/child.vue | 0
.../define-options-inherit-attrs-false.vue | 0
.../base}/inherit-attrs-false-v-bind.vue | 0
.../base}/inherit-attrs-false.vue | 0
.../base}/main.vue | 0
.../duplicateNameEvent}/basic.vue | 0
.../duplicateNameEvent}/child.vue | 0
.../duplicateNameEvent}/main.vue | 0
.../duplicateNameProp}/basic.vue | 0
.../duplicateNameProp}/child.vue | 0
.../duplicateNameProp}/main.vue | 0
.../requiredProp}/basic.vue | 0
.../requiredProp}/child.vue | 0
.../requiredProp}/main.vue | 0
.../tsconfig.json | 8 +++++++
.../unknownTag}/basic.vue | 0
.../unknownTag}/main.vue | 0
.../vue2_strictTemplate/tsconfig.json | 1 -
test-workspace/tsc/tsconfig.json | 2 ++
30 files changed, 36 insertions(+), 28 deletions(-)
create mode 100644 test-workspace/tsc/passedFixtures/fallthroughAttributes/tsconfig.json
rename test-workspace/tsc/passedFixtures/{vue3/inheritAttrs_unknownTag => fallthroughAttributes/unknownTag}/basic.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3/inheritAttrs_unknownTag => fallthroughAttributes/unknownTag}/main.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate => fallthroughAttributes_strictTemplate}/#4699/HelloWorld.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate => fallthroughAttributes_strictTemplate}/#4699/main.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs => fallthroughAttributes_strictTemplate/base}/basic.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs => fallthroughAttributes_strictTemplate/base}/child.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs => fallthroughAttributes_strictTemplate/base}/define-options-inherit-attrs-false.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs => fallthroughAttributes_strictTemplate/base}/inherit-attrs-false-v-bind.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs => fallthroughAttributes_strictTemplate/base}/inherit-attrs-false.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs => fallthroughAttributes_strictTemplate/base}/main.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_duplicateNameEvent => fallthroughAttributes_strictTemplate/duplicateNameEvent}/basic.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_duplicateNameEvent => fallthroughAttributes_strictTemplate/duplicateNameEvent}/child.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_duplicateNameEvent => fallthroughAttributes_strictTemplate/duplicateNameEvent}/main.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_duplicateNameProp => fallthroughAttributes_strictTemplate/duplicateNameProp}/basic.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_duplicateNameProp => fallthroughAttributes_strictTemplate/duplicateNameProp}/child.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_duplicateNameProp => fallthroughAttributes_strictTemplate/duplicateNameProp}/main.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_requiredProp => fallthroughAttributes_strictTemplate/requiredProp}/basic.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_requiredProp => fallthroughAttributes_strictTemplate/requiredProp}/child.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_requiredProp => fallthroughAttributes_strictTemplate/requiredProp}/main.vue (100%)
create mode 100644 test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/tsconfig.json
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_unknownTag => fallthroughAttributes_strictTemplate/unknownTag}/basic.vue (100%)
rename test-workspace/tsc/passedFixtures/{vue3_strictTemplate/inheritAttrs_unknownTag => fallthroughAttributes_strictTemplate/unknownTag}/main.vue (100%)
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index be157ff333..42026ad78b 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -288,8 +288,11 @@ export function* generateComponent(
}
if (
- node.props.some(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && prop.name === 'bind' && prop.exp?.loc.source === '$attrs')
- || node === ctx.singleRootNode
+ options.vueCompilerOptions.fallthroughAttributes
+ && (
+ node.props.some(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && prop.name === 'bind' && prop.exp?.loc.source === '$attrs')
+ || node === ctx.singleRootNode
+ )
) {
const varAttrs = ctx.getInternalVariable();
ctx.inheritedAttrVars.add(varAttrs);
@@ -386,8 +389,11 @@ export function* generateElement(
}
if (
- node.props.some(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && prop.name === 'bind' && prop.exp?.loc.source === '$attrs')
- || node === ctx.singleRootNode
+ options.vueCompilerOptions.fallthroughAttributes
+ && (
+ node.props.some(prop => prop.type === CompilerDOM.NodeTypes.DIRECTIVE && prop.name === 'bind' && prop.exp?.loc.source === '$attrs')
+ || node === ctx.singleRootNode
+ )
) {
ctx.inheritedAttrVars.add(`__VLS_intrinsicElements.${node.tag}`);
}
diff --git a/packages/language-core/lib/types.ts b/packages/language-core/lib/types.ts
index 17158d277e..11860c48de 100644
--- a/packages/language-core/lib/types.ts
+++ b/packages/language-core/lib/types.ts
@@ -30,6 +30,7 @@ export interface VueCompilerOptions {
jsxSlots: boolean;
strictTemplates: boolean;
skipTemplateCodegen: boolean;
+ fallthroughAttributes: boolean;
dataAttributes: string[];
htmlAttributes: string[];
optionsWrapper: [string, string] | [];
diff --git a/packages/language-core/lib/utils/ts.ts b/packages/language-core/lib/utils/ts.ts
index 18d21ad14c..b17874e8ff 100644
--- a/packages/language-core/lib/utils/ts.ts
+++ b/packages/language-core/lib/utils/ts.ts
@@ -216,6 +216,7 @@ export function resolveVueCompilerOptions(vueOptions: Partial = {
`;
exports[`vue-tsc-dts > Input: generic/main.vue, Output: generic/main.vue.d.ts 1`] = `
-"declare const _default: import("vue").DefineComponent<__VLS_TypePropsToOption<__VLS_OmitIndexSignature any;
- onBar?: (data: number) => any;
- title?: string;
- foo: number;
-} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps>>>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly any;
- onBar?: (data: number) => any;
- title?: string;
- foo: number;
-} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps>>>>>, {}, {}>;
+"declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly>, {}, {}>;
export default _default;
-type __VLS_NonUndefinedable = T extends undefined ? never : T;
-type __VLS_TypePropsToOption = {
- [K in keyof T]-?: {} extends Pick ? {
- type: import('vue').PropType<__VLS_NonUndefinedable>;
- } : {
- type: import('vue').PropType;
- required: true;
- };
-};
-type __VLS_OmitIndexSignature = {
- [K in keyof T as {} extends Record ? never : K]: T[K];
-};
"
`;
diff --git a/test-workspace/tsc/passedFixtures/fallthroughAttributes/tsconfig.json b/test-workspace/tsc/passedFixtures/fallthroughAttributes/tsconfig.json
new file mode 100644
index 0000000000..d5a2c81e67
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/fallthroughAttributes/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "vueCompilerOptions": {
+ "fallthroughAttributes": true,
+ },
+ "include": [ "**/*" ],
+}
diff --git a/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/basic.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes/unknownTag/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/basic.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes/unknownTag/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes/unknownTag/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3/inheritAttrs_unknownTag/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes/unknownTag/main.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/#4699/HelloWorld.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/#4699/HelloWorld.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/#4699/HelloWorld.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/#4699/HelloWorld.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/#4699/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/#4699/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/#4699/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/#4699/main.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/basic.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/basic.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/child.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/child.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/child.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/child.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/define-options-inherit-attrs-false.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/define-options-inherit-attrs-false.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/define-options-inherit-attrs-false.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/define-options-inherit-attrs-false.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/inherit-attrs-false-v-bind.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/inherit-attrs-false-v-bind.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/inherit-attrs-false-v-bind.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/inherit-attrs-false-v-bind.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/inherit-attrs-false.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/inherit-attrs-false.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/inherit-attrs-false.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/inherit-attrs-false.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/base/main.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/basic.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameEvent/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/basic.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameEvent/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/child.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameEvent/child.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/child.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameEvent/child.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameEvent/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameEvent/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameEvent/main.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/basic.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameProp/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/basic.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameProp/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/child.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameProp/child.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/child.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameProp/child.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameProp/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_duplicateNameProp/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/duplicateNameProp/main.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/basic.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/requiredProp/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/basic.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/requiredProp/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/child.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/requiredProp/child.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/child.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/requiredProp/child.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/requiredProp/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_requiredProp/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/requiredProp/main.vue
diff --git a/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/tsconfig.json b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/tsconfig.json
new file mode 100644
index 0000000000..e93dd518af
--- /dev/null
+++ b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "vueCompilerOptions": {
+ "fallthroughAttributes": true,
+ "strictTemplates": true,
+ },
+ "include": [ "**/*" ],
+}
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/basic.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/unknownTag/basic.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/basic.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/unknownTag/basic.vue
diff --git a/test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/main.vue b/test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/unknownTag/main.vue
similarity index 100%
rename from test-workspace/tsc/passedFixtures/vue3_strictTemplate/inheritAttrs_unknownTag/main.vue
rename to test-workspace/tsc/passedFixtures/fallthroughAttributes_strictTemplate/unknownTag/main.vue
diff --git a/test-workspace/tsc/passedFixtures/vue2_strictTemplate/tsconfig.json b/test-workspace/tsc/passedFixtures/vue2_strictTemplate/tsconfig.json
index 2011fc02db..141c51abdd 100644
--- a/test-workspace/tsc/passedFixtures/vue2_strictTemplate/tsconfig.json
+++ b/test-workspace/tsc/passedFixtures/vue2_strictTemplate/tsconfig.json
@@ -12,6 +12,5 @@
"../vue3_strictTemplate/#3140",
"../vue3_strictTemplate/#3718",
"../vue3_strictTemplate/intrinsicProps",
- "../vue3_strictTemplate/inheritAttrs",
]
}
diff --git a/test-workspace/tsc/tsconfig.json b/test-workspace/tsc/tsconfig.json
index 714f41f63f..ecc8bdbcc3 100644
--- a/test-workspace/tsc/tsconfig.json
+++ b/test-workspace/tsc/tsconfig.json
@@ -14,6 +14,8 @@
{ "path": "./passedFixtures/#3819" },
{ "path": "./passedFixtures/#4503" },
{ "path": "./passedFixtures/core#9923" },
+ { "path": "./passedFixtures/fallthroughAttributes" },
+ { "path": "./passedFixtures/fallthroughAttributes_strictTemplate" },
{ "path": "./passedFixtures/noPropertyAccessFromIndexSignature" },
// { "path": "./passedFixtures/petite-vue" },
{ "path": "./passedFixtures/pug" },
From 180af0bed813b1e90ddab437f86ce5919373a713 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Tue, 27 Aug 2024 23:29:28 +0800
Subject: [PATCH 08/93] fix(language-core): fix __VLS_template returns when
skipTemplateCodegen enabled
---
packages/language-core/lib/codegen/script/template.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts
index 582b9a1345..3a895a603c 100644
--- a/packages/language-core/lib/codegen/script/template.ts
+++ b/packages/language-core/lib/codegen/script/template.ts
@@ -39,7 +39,7 @@ export function* generateTemplate(
const templateUsageVars = [...getTemplateUsageVars(options, ctx)];
yield `// @ts-ignore${newLine}`;
yield `[${templateUsageVars.join(', ')}]${newLine}`;
- yield `return [{}, {}] as const${endOfLine}`;
+ yield `return { slots: {}, refs: {}, attrs: {} }${endOfLine}`;
yield `}${newLine}`;
}
}
From 5936c8281888227e66bdb86c809222c944cc2c5b Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Wed, 28 Aug 2024 00:13:27 +0800
Subject: [PATCH 09/93] refactor(language-core): reduce virtual code generated
by component tags (#4714)
---
.../lib/codegen/script/globalTypes.ts | 9 +-
.../language-core/lib/codegen/script/index.ts | 1 +
.../lib/codegen/script/template.ts | 2 +-
.../lib/codegen/template/context.ts | 7 +-
.../lib/codegen/template/element.ts | 139 +++++++-----------
.../lib/codegen/template/elementChildren.ts | 1 +
.../lib/codegen/template/elementProps.ts | 32 +++-
.../lib/codegen/template/index.ts | 15 +-
.../lib/codegen/template/templateChild.ts | 2 +-
packages/language-core/lib/plugins/vue-tsx.ts | 5 +
packages/language-core/lib/types.ts | 3 +
packages/language-server/lib/initialize.ts | 1 +
packages/language-server/node.ts | 1 +
.../language-server/tests/completions.spec.ts | 6 +
14 files changed, 123 insertions(+), 101 deletions(-)
diff --git a/packages/language-core/lib/codegen/script/globalTypes.ts b/packages/language-core/lib/codegen/script/globalTypes.ts
index 70125ca668..9638adef0f 100644
--- a/packages/language-core/lib/codegen/script/globalTypes.ts
+++ b/packages/language-core/lib/codegen/script/globalTypes.ts
@@ -67,7 +67,10 @@ declare global {
function __VLS_nonNullable(t: T): T extends null | undefined ? never : T;
type __VLS_SelfComponent = string extends N ? {} : N extends string ? { [P in N]: C } : {};
- type __VLS_WithComponent =
+ type __VLS_WithComponent =
+ N1 extends keyof Ctx ? N1 extends N0 ? Pick : { [K in N0]: Ctx[N1] } :
+ N2 extends keyof Ctx ? N2 extends N0 ? Pick : { [K in N0]: Ctx[N2] } :
+ N3 extends keyof Ctx ? N3 extends N0 ? Pick : { [K in N0]: Ctx[N3] } :
N1 extends keyof LocalComponents ? N1 extends N0 ? Pick : { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? N2 extends N0 ? Pick : { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? N3 extends N0 ? Pick : { [K in N0]: LocalComponents[N3] } :
@@ -88,10 +91,10 @@ declare global {
: (_: {}${vueCompilerOptions.strictTemplates ? '' : ' & Record'}, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: {}${vueCompilerOptions.strictTemplates ? '' : ' & Record'} } };
function __VLS_elementAsFunction(tag: T, endTag?: T): (_: T${vueCompilerOptions.strictTemplates ? '' : ' & Record'}) => void;
function __VLS_functionalComponentArgsRest any>(t: T): Parameters['length'] extends 2 ? [any] : [];
- function __VLS_pickFunctionalComponentCtx(comp: T, compInstance: K): __VLS_PickNotAny<
+ function __VLS_pickFunctionalComponentCtx(comp: T, compInstance: K): NonNullable<__VLS_PickNotAny<
'__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
- >;
+ >>;
type __VLS_FunctionalComponentProps =
'__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: { props?: infer P } } ? NonNullable : never
: T extends (props: infer P, ...args: any) => any ? P :
diff --git a/packages/language-core/lib/codegen/script/index.ts b/packages/language-core/lib/codegen/script/index.ts
index ec48ad0a81..92da84d736 100644
--- a/packages/language-core/lib/codegen/script/index.ts
+++ b/packages/language-core/lib/codegen/script/index.ts
@@ -45,6 +45,7 @@ export interface ScriptCodegenOptions {
scriptSetupRanges: ScriptSetupRanges | undefined;
templateCodegen: TemplateCodegenContext & { codes: Code[]; } | undefined;
globalTypes: boolean;
+ edited: boolean;
getGeneratedLength: () => number;
linkedCodeMappings: Mapping[];
}
diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts
index 3a895a603c..c7c8a9cbcf 100644
--- a/packages/language-core/lib/codegen/script/template.ts
+++ b/packages/language-core/lib/codegen/script/template.ts
@@ -23,7 +23,7 @@ export function* generateTemplate(
else {
yield `const __VLS_template = (() => {${newLine}`;
}
- const templateCodegenCtx = createTemplateCodegenContext(new Set());
+ const templateCodegenCtx = createTemplateCodegenContext({ scriptSetupBindingNames: new Set(), edited: options.edited });
yield `const __VLS_template_return = () => {${newLine}`;
yield* generateCtx(options, isClassComponent);
yield* generateTemplateContext(options, templateCodegenCtx);
diff --git a/packages/language-core/lib/codegen/template/context.ts b/packages/language-core/lib/codegen/template/context.ts
index 480643d1a8..85c1548aa1 100644
--- a/packages/language-core/lib/codegen/template/context.ts
+++ b/packages/language-core/lib/codegen/template/context.ts
@@ -57,7 +57,7 @@ const _codeFeatures = {
export type TemplateCodegenContext = ReturnType;
-export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCodegenOptions['scriptSetupBindingNames']) {
+export function createTemplateCodegenContext(options: Pick) {
let ignoredError = false;
let expectErrorToken: {
errors: number;
@@ -190,6 +190,9 @@ export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCo
}
},
generateAutoImportCompletion: function* (): Generator {
+ if (!options.edited) {
+ return;
+ }
const all = [...accessExternalVariables.entries()];
if (!all.some(([_, offsets]) => offsets.size)) {
return;
@@ -198,7 +201,7 @@ export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCo
yield `[`;
for (const [varName, offsets] of all) {
for (const offset of offsets) {
- if (scriptSetupBindingNames.has(varName)) {
+ if (options.scriptSetupBindingNames.has(varName)) {
// #3409
yield [
varName,
diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts
index 42026ad78b..2a3edac1da 100644
--- a/packages/language-core/lib/codegen/template/element.ts
+++ b/packages/language-core/lib/codegen/template/element.ts
@@ -23,8 +23,7 @@ export function* generateComponent(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
- currentComponent: CompilerDOM.ElementNode | undefined,
- componentCtxVar: string | undefined
+ currentComponent: CompilerDOM.ElementNode | undefined
): Generator {
const startTagOffset = node.loc.start.offset + options.template.content.substring(node.loc.start.offset).indexOf(node.tag);
const endTagOffset = !node.isSelfClosing && options.template.lang === 'html' ? node.loc.start.offset + node.loc.source.lastIndexOf(node.tag) : undefined;
@@ -137,40 +136,26 @@ export function* generateComponent(
yield `)${endOfLine}`;
}
else if (!isComponentTag) {
- yield `// @ts-ignore${newLine}`;
- yield `const ${var_originalComponent} = ({} as `;
- for (const componentName of possibleOriginalNames) {
- yield `'${componentName}' extends keyof typeof __VLS_ctx ? { '${getCanonicalComponentName(node.tag)}': typeof __VLS_ctx`;
- yield* generatePropertyAccess(options, ctx, componentName);
- yield ` }: `;
- }
- yield `typeof __VLS_resolvedLocalAndGlobalComponents)${newLine}`;
- yield* generatePropertyAccess(
- options,
- ctx,
- getCanonicalComponentName(node.tag),
+ yield `const ${var_originalComponent} = __VLS_resolvedLocalAndGlobalComponents.`;
+ yield* generateCanonicalComponentName(
+ node.tag,
startTagOffset,
- ctx.codeFeatures.verification
+ {
+ // with hover support
+ ...ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation,
+ ...ctx.codeFeatures.verification,
+ }
);
- yield endOfLine;
+ yield `${endOfLine}`;
- // hover support
- for (const offset of tagOffsets) {
- yield `({} as { ${getCanonicalComponentName(node.tag)}: typeof ${var_originalComponent} }).`;
- yield* generateCanonicalComponentName(
- node.tag,
- offset,
- ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation
- );
- yield endOfLine;
- }
const camelizedTag = camelize(node.tag);
if (variableNameRegex.test(camelizedTag)) {
// renaming / find references support
+ yield `/** @type { [`;
for (const tagOffset of tagOffsets) {
for (const shouldCapitalize of (node.tag[0] === node.tag[0].toUpperCase() ? [false] : [true, false])) {
const expectName = shouldCapitalize ? capitalize(camelizedTag) : camelizedTag;
- yield `__VLS_components.`;
+ yield `typeof __VLS_components.`;
yield* generateCamelized(
shouldCapitalize ? capitalize(node.tag) : node.tag,
tagOffset,
@@ -181,17 +166,16 @@ export function* generateComponent(
},
}
);
- yield `;`;
+ yield `, `;
}
}
- yield `${newLine}`;
+ yield `] } */${newLine}`;
// auto import support
- yield `// @ts-ignore${newLine}`; // #2304
- yield `[`;
- for (const tagOffset of tagOffsets) {
+ if (options.edited) {
+ yield `// @ts-ignore${newLine}`; // #2304
yield* generateCamelized(
capitalize(node.tag),
- tagOffset,
+ startTagOffset,
{
completion: {
isAdditional: true,
@@ -199,9 +183,8 @@ export function* generateComponent(
},
}
);
- yield `,`;
+ yield `${endOfLine}`;
}
- yield `]${endOfLine}`;
}
}
else {
@@ -213,38 +196,17 @@ export function* generateComponent(
yield* generateElementProps(options, ctx, node, props, false);
yield `}))${endOfLine}`;
- if (options.vueCompilerOptions.strictTemplates) {
- // with strictTemplates, generate once for props type-checking + instance type
- yield `const ${var_componentInstance} = ${var_functionalComponent}(`;
- yield* wrapWith(
- startTagOffset,
- startTagOffset + node.tag.length,
- ctx.codeFeatures.verification,
- `{`,
- ...generateElementProps(options, ctx, node, props, true, propsFailedExps),
- `}`
- );
- yield `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${endOfLine}`;
- }
- else {
- // without strictTemplates, this only for instance type
- yield `const ${var_componentInstance} = ${var_functionalComponent}({`;
- yield* generateElementProps(options, ctx, node, props, false);
- yield `}, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${endOfLine}`;
- // and this for props type-checking
- yield `({} as (props: __VLS_FunctionalComponentProps & Record) => void)(`;
- yield* wrapWith(
- startTagOffset,
- startTagOffset + node.tag.length,
- ctx.codeFeatures.verification,
- `{`,
- ...generateElementProps(options, ctx, node, props, true, propsFailedExps),
- `}`
- );
- yield `)${endOfLine}`;
- }
+ yield `const ${var_componentInstance} = ${var_functionalComponent}(`;
+ yield* wrapWith(
+ startTagOffset,
+ startTagOffset + node.tag.length,
+ ctx.codeFeatures.verification,
+ `{`,
+ ...generateElementProps(options, ctx, node, props, true, propsFailedExps),
+ `}`
+ );
+ yield `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${endOfLine}`;
- componentCtxVar = var_defineComponentCtx;
currentComponent = node;
for (const failedExp of propsFailedExps) {
@@ -262,28 +224,14 @@ export function* generateComponent(
}
const refName = yield* generateVScope(options, ctx, node, props);
+ if (refName) {
+ ctx.usedComponentCtxVars.add(var_defineComponentCtx);
+ }
- ctx.usedComponentCtxVars.add(componentCtxVar);
const usedComponentEventsVar = yield* generateElementEvents(options, ctx, node, var_functionalComponent, var_componentInstance, var_componentEmit, var_componentEvents);
-
- if (var_defineComponentCtx && ctx.usedComponentCtxVars.has(var_defineComponentCtx)) {
- yield `const ${componentCtxVar} = __VLS_nonNullable(__VLS_pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance}))${endOfLine}`;
- if (refName) {
- yield `// @ts-ignore${newLine}`;
- if (node.codegenNode?.type === CompilerDOM.NodeTypes.VNODE_CALL
- && node.codegenNode.props?.type === CompilerDOM.NodeTypes.JS_OBJECT_EXPRESSION
- && node.codegenNode.props.properties.find(({ key }) => key.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && key.content === 'ref_for')
- ) {
- yield `(${refName} ??= []).push(${var_defineComponentCtx})`;
- } else {
- yield `${refName} = ${var_defineComponentCtx}`;
- }
-
- yield endOfLine;
- }
- }
if (usedComponentEventsVar) {
- yield `let ${var_componentEmit}!: typeof ${componentCtxVar}.emit${endOfLine}`;
+ ctx.usedComponentCtxVars.add(var_defineComponentCtx);
+ yield `let ${var_componentEmit}!: typeof ${var_defineComponentCtx}.emit${endOfLine}`;
yield `let ${var_componentEvents}!: __VLS_NormalizeEmits${endOfLine}`;
}
@@ -301,10 +249,27 @@ export function* generateComponent(
const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot') as CompilerDOM.DirectiveNode;
if (slotDir) {
- yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, componentCtxVar);
+ yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, var_defineComponentCtx);
}
else {
- yield* generateElementChildren(options, ctx, node, currentComponent, componentCtxVar);
+ yield* generateElementChildren(options, ctx, node, currentComponent, var_defineComponentCtx);
+ }
+
+ if (ctx.usedComponentCtxVars.has(var_defineComponentCtx)) {
+ yield `const ${var_defineComponentCtx} = __VLS_pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance})${endOfLine}`;
+ if (refName) {
+ yield `// @ts-ignore${newLine}`;
+ if (node.codegenNode?.type === CompilerDOM.NodeTypes.VNODE_CALL
+ && node.codegenNode.props?.type === CompilerDOM.NodeTypes.JS_OBJECT_EXPRESSION
+ && node.codegenNode.props.properties.find(({ key }) => key.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && key.content === 'ref_for')
+ ) {
+ yield `(${refName} ??= []).push(${var_defineComponentCtx})`;
+ } else {
+ yield `${refName} = ${var_defineComponentCtx}`;
+ }
+
+ yield endOfLine;
+ }
}
}
diff --git a/packages/language-core/lib/codegen/template/elementChildren.ts b/packages/language-core/lib/codegen/template/elementChildren.ts
index 67e38651c1..a184a2c798 100644
--- a/packages/language-core/lib/codegen/template/elementChildren.ts
+++ b/packages/language-core/lib/codegen/template/elementChildren.ts
@@ -28,6 +28,7 @@ export function* generateElementChildren(
&& node.tagType !== CompilerDOM.ElementTypes.ELEMENT
&& node.tagType !== CompilerDOM.ElementTypes.TEMPLATE
) {
+ ctx.usedComponentCtxVars.add(componentCtxVar);
yield `__VLS_nonNullable(${componentCtxVar}.slots).`;
yield* wrapWith(
node.children[0].loc.start.offset,
diff --git a/packages/language-core/lib/codegen/template/elementProps.ts b/packages/language-core/lib/codegen/template/elementProps.ts
index 780e9d9618..5d4960192a 100644
--- a/packages/language-core/lib/codegen/template/elementProps.ts
+++ b/packages/language-core/lib/codegen/template/elementProps.ts
@@ -109,6 +109,7 @@ export function* generateElementProps(
if (shouldSpread) {
yield `...{ `;
}
+ const codeInfo = ctx.codeFeatures.withoutHighlightAndCompletion;
const codes = wrapWith(
prop.loc.start.offset,
prop.loc.end.offset,
@@ -121,8 +122,20 @@ export function* generateElementProps(
propName,
prop.arg.loc.start.offset,
{
- ...ctx.codeFeatures.withoutHighlightAndCompletion,
- navigation: ctx.codeFeatures.withoutHighlightAndCompletion.navigation
+ ...codeInfo,
+ verification: options.vueCompilerOptions.strictTemplates
+ ? codeInfo.verification
+ : {
+ shouldReport(_source, code) {
+ if (String(code) === '2353' || String(code) === '2561') {
+ return false;
+ }
+ return typeof codeInfo.verification === 'object'
+ ? codeInfo.verification.shouldReport?.(_source, code) ?? true
+ : true;
+ },
+ },
+ navigation: codeInfo.navigation
? {
resolveRenameNewName: camelize,
resolveRenameEditText: shouldCamelize ? hyphenateAttr : undefined,
@@ -183,6 +196,7 @@ export function* generateElementProps(
if (shouldSpread) {
yield `...{ `;
}
+ const codeInfo = ctx.codeFeatures.withoutHighlightAndCompletion;
const codes = conditionWrapWith(
enableCodeFeatures,
prop.loc.start.offset,
@@ -195,7 +209,19 @@ export function* generateElementProps(
prop.loc.start.offset,
shouldCamelize
? {
- ...ctx.codeFeatures.withoutHighlightAndCompletion,
+ ...codeInfo,
+ verification: options.vueCompilerOptions.strictTemplates
+ ? codeInfo.verification
+ : {
+ shouldReport(_source, code) {
+ if (String(code) === '2353' || String(code) === '2561') {
+ return false;
+ }
+ return typeof codeInfo.verification === 'object'
+ ? codeInfo.verification.shouldReport?.(_source, code) ?? true
+ : true;
+ },
+ },
navigation: ctx.codeFeatures.withoutHighlightAndCompletion.navigation
? {
resolveRenameNewName: camelize,
diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts
index a338437e97..b6aa1f43ce 100644
--- a/packages/language-core/lib/codegen/template/index.ts
+++ b/packages/language-core/lib/codegen/template/index.ts
@@ -15,6 +15,7 @@ export interface TemplateCodegenOptions {
template: NonNullable;
scriptSetupBindingNames: Set;
scriptSetupImportComponentNames: Set;
+ edited: boolean;
templateRefNames: Map;
hasDefineSlots?: boolean;
slotsAssignName?: string;
@@ -23,7 +24,7 @@ export interface TemplateCodegenOptions {
}
export function* generateTemplate(options: TemplateCodegenOptions): Generator {
- const ctx = createTemplateCodegenContext(options.scriptSetupBindingNames);
+ const ctx = createTemplateCodegenContext(options);
if (options.slotsAssignName) {
ctx.addLocalVariable(options.slotsAssignName);
@@ -105,15 +106,21 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator {
- yield `let __VLS_resolvedLocalAndGlobalComponents!: {}`;
+ yield `let __VLS_resolvedLocalAndGlobalComponents!: Required<{}`;
if (options.template.ast) {
+ const components = new Set();
for (const node of forEachElementNode(options.template.ast)) {
if (
node.tagType === CompilerDOM.ElementTypes.COMPONENT
&& node.tag.toLowerCase() !== 'component'
&& !node.tag.includes('.') // namespace tag
) {
- yield ` & __VLS_WithComponent<'${getCanonicalComponentName(node.tag)}', typeof __VLS_localComponents, `;
+ if (components.has(node.tag)) {
+ continue;
+ }
+ components.add(node.tag);
+ yield newLine;
+ yield ` & __VLS_WithComponent<'${getCanonicalComponentName(node.tag)}', typeof __VLS_ctx, typeof __VLS_localComponents, `;
yield getPossibleOriginalComponentNames(node.tag, false)
.map(name => `"${name}"`)
.join(', ');
@@ -121,7 +128,7 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator${endOfLine}`;
}
}
diff --git a/packages/language-core/lib/codegen/template/templateChild.ts b/packages/language-core/lib/codegen/template/templateChild.ts
index 999c0d4709..ad3608242f 100644
--- a/packages/language-core/lib/codegen/template/templateChild.ts
+++ b/packages/language-core/lib/codegen/template/templateChild.ts
@@ -80,7 +80,7 @@ export function* generateTemplateChild(
yield* generateElement(options, ctx, node, currentComponent, componentCtxVar);
}
else {
- yield* generateComponent(options, ctx, node, currentComponent, componentCtxVar);
+ yield* generateComponent(options, ctx, node, currentComponent);
}
}
}
diff --git a/packages/language-core/lib/plugins/vue-tsx.ts b/packages/language-core/lib/plugins/vue-tsx.ts
index a84dfef4b2..c5e1308e9c 100644
--- a/packages/language-core/lib/plugins/vue-tsx.ts
+++ b/packages/language-core/lib/plugins/vue-tsx.ts
@@ -9,6 +9,8 @@ import type { Code, Sfc, VueLanguagePlugin } from '../types';
export const tsCodegen = new WeakMap>();
+const fileEditTimes = new Map();
+
const plugin: VueLanguagePlugin = ctx => {
return {
@@ -92,6 +94,7 @@ function createTsx(
compilerOptions: ctx.compilerOptions,
vueCompilerOptions: ctx.vueCompilerOptions,
template: _sfc.template,
+ edited: ctx.vueCompilerOptions.__test || (fileEditTimes.get(fileName) ?? 0) >= 2,
scriptSetupBindingNames: scriptSetupBindingNames(),
scriptSetupImportComponentNames: scriptSetupImportComponentNames(),
templateRefNames: new Map(),
@@ -157,9 +160,11 @@ function createTsx(
templateCodegen: _template,
compilerOptions: ctx.compilerOptions,
vueCompilerOptions: ctx.vueCompilerOptions,
+ edited: ctx.vueCompilerOptions.__test || (fileEditTimes.get(fileName) ?? 0) >= 2,
getGeneratedLength: () => generatedLength,
linkedCodeMappings,
});
+ fileEditTimes.set(fileName, (fileEditTimes.get(fileName) ?? 0) + 1);
let current = codegen.next();
diff --git a/packages/language-core/lib/types.ts b/packages/language-core/lib/types.ts
index 11860c48de..57dfd05898 100644
--- a/packages/language-core/lib/types.ts
+++ b/packages/language-core/lib/types.ts
@@ -53,6 +53,9 @@ export interface VueCompilerOptions {
experimentalDefinePropProposal: 'kevinEdition' | 'johnsonEdition' | false;
experimentalResolveStyleCssClasses: 'scoped' | 'always' | 'never';
experimentalModelPropName: Record | Record[]>>;
+
+ // internal
+ __test?: boolean;
}
export const validVersions = [2, 2.1] as const;
diff --git a/packages/language-server/lib/initialize.ts b/packages/language-server/lib/initialize.ts
index 450353bfcb..bfb91fb916 100644
--- a/packages/language-server/lib/initialize.ts
+++ b/packages/language-server/lib/initialize.ts
@@ -37,6 +37,7 @@ export function initialize(
compilerOptions = ts.getDefaultCompilerOptions();
vueCompilerOptions = resolveVueCompilerOptions({});
}
+ vueCompilerOptions.__test = params.initializationOptions.typescript.disableAutoImportCache;
updateFileWatcher(vueCompilerOptions);
return {
languagePlugins: [createVueLanguagePlugin2(
diff --git a/packages/language-server/node.ts b/packages/language-server/node.ts
index 541467169d..65b4c4d787 100644
--- a/packages/language-server/node.ts
+++ b/packages/language-server/node.ts
@@ -26,6 +26,7 @@ connection.onInitialize(params => {
vueOptions: resolveVueCompilerOptions({}),
options: ts.getDefaultCompilerOptions(),
};
+ commandLine.vueOptions.__test = params.initializationOptions.typescript.disableAutoImportCache;
return {
languagePlugins: [createVueLanguagePlugin2(
ts,
diff --git a/packages/language-server/tests/completions.spec.ts b/packages/language-server/tests/completions.spec.ts
index 96c9624688..044f28966f 100644
--- a/packages/language-server/tests/completions.spec.ts
+++ b/packages/language-server/tests/completions.spec.ts
@@ -338,6 +338,12 @@ describe('Completions', async () => {
},
},
],
+ "commitCharacters": [
+ ".",
+ ",",
+ ";",
+ "(",
+ ],
"detail": "Add import from "./ComponentForAutoImport.vue"
(property) default: DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly>, {}, {}>",
"documentation": {
From 13924d1d2fb8a6f11c267dd4612c366502c1cbc5 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Wed, 28 Aug 2024 02:55:26 +0800
Subject: [PATCH 10/93] refactor(language-core): do not wrap template virtual
code with function (#4731)
---
.../lib/codegen/script/component.ts | 2 +-
.../lib/codegen/script/globalTypes.ts | 6 +-
.../language-core/lib/codegen/script/index.ts | 27 ++--
.../lib/codegen/script/internalComponent.ts | 3 +-
.../lib/codegen/script/scriptSetup.ts | 4 +-
.../lib/codegen/script/template.ts | 131 ++++++++----------
.../lib/codegen/template/index.ts | 2 +-
.../tsc/tests/__snapshots__/dts.spec.ts.snap | 92 +++++++-----
8 files changed, 130 insertions(+), 137 deletions(-)
diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts
index fa49ad1791..457ba0c133 100644
--- a/packages/language-core/lib/codegen/script/component.ts
+++ b/packages/language-core/lib/codegen/script/component.ts
@@ -142,7 +142,7 @@ export function* generatePropsOption(
optionExpCodes.push(generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.navigation));
}
if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) {
- let attrsType = `ReturnType['attrs']`;
+ let attrsType = `typeof __VLS_templateResult['attrs']`;
if (hasEmitsOption) {
attrsType = `Omit<${attrsType}, \`on\${string}\`>`;
}
diff --git a/packages/language-core/lib/codegen/script/globalTypes.ts b/packages/language-core/lib/codegen/script/globalTypes.ts
index 9638adef0f..541a1512d3 100644
--- a/packages/language-core/lib/codegen/script/globalTypes.ts
+++ b/packages/language-core/lib/codegen/script/globalTypes.ts
@@ -66,11 +66,7 @@ declare global {
function __VLS_makeOptional(t: T): { [K in keyof T]?: T[K] };
function __VLS_nonNullable(t: T): T extends null | undefined ? never : T;
- type __VLS_SelfComponent = string extends N ? {} : N extends string ? { [P in N]: C } : {};
- type __VLS_WithComponent =
- N1 extends keyof Ctx ? N1 extends N0 ? Pick : { [K in N0]: Ctx[N1] } :
- N2 extends keyof Ctx ? N2 extends N0 ? Pick : { [K in N0]: Ctx[N2] } :
- N3 extends keyof Ctx ? N3 extends N0 ? Pick : { [K in N0]: Ctx[N3] } :
+ type __VLS_WithComponent =
N1 extends keyof LocalComponents ? N1 extends N0 ? Pick : { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? N2 extends N0 ? Pick : { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? N3 extends N0 ? Pick : { [K in N0]: LocalComponents[N3] } :
diff --git a/packages/language-core/lib/codegen/script/index.ts b/packages/language-core/lib/codegen/script/index.ts
index 92da84d736..322eaebd01 100644
--- a/packages/language-core/lib/codegen/script/index.ts
+++ b/packages/language-core/lib/codegen/script/index.ts
@@ -101,9 +101,16 @@ export function* generateScript(options: ScriptCodegenOptions): Generator {`;
+ yield* generateTemplate(options, ctx, true);
+ yield `},${newLine}`;
+ yield generateSfcBlockSection(options.sfc.script, classBlockEnd, options.sfc.script.content.length, codeFeatures.all);
+ }
}
else {
yield generateSfcBlockSection(options.sfc.script, 0, options.sfc.script.content.length, codeFeatures.all);
@@ -118,12 +125,7 @@ export function* generateScript(options: ScriptCodegenOptions): Generator {
if (options.sfc.scriptSetup && options.scriptSetupRanges) {
- yield `let __VLS_defineComponent!: typeof import('${options.vueCompilerOptions.lib}').defineComponent${endOfLine}`;
- yield `const __VLS_internalComponent = __VLS_defineComponent({${newLine}`;
+ yield `const __VLS_internalComponent = (await import('${options.vueCompilerOptions.lib}')).defineComponent({${newLine}`;
yield `setup() {${newLine}`;
yield `return {${newLine}`;
if (ctx.bypassDefineComponent) {
diff --git a/packages/language-core/lib/codegen/script/scriptSetup.ts b/packages/language-core/lib/codegen/script/scriptSetup.ts
index 6c6c014597..0e99fa781c 100644
--- a/packages/language-core/lib/codegen/script/scriptSetup.ts
+++ b/packages/language-core/lib/codegen/script/scriptSetup.ts
@@ -280,8 +280,8 @@ function* generateSetupFunction(
yield* generateModelEmits(options, scriptSetup, scriptSetupRanges);
yield* generateStyleModules(options, ctx);
yield* generateTemplate(options, ctx, false);
- yield `type __VLS_Refs = ReturnType['refs']${endOfLine}`;
- yield `type __VLS_Slots = ReturnType['slots']${endOfLine}`;
+ yield `type __VLS_Refs = typeof __VLS_templateResult['refs']${endOfLine}`;
+ yield `type __VLS_Slots = typeof __VLS_templateResult['slots']${endOfLine}`;
if (syntax) {
if (!options.vueCompilerOptions.skipTemplateCodegen && (options.templateCodegen?.hasSlot || scriptSetupRanges?.slots.define)) {
diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts
index c7c8a9cbcf..7507e2dffd 100644
--- a/packages/language-core/lib/codegen/script/template.ts
+++ b/packages/language-core/lib/codegen/script/template.ts
@@ -4,114 +4,99 @@ import { getSlotsPropertyName, hyphenateTag } from '../../utils/shared';
import { endOfLine, newLine } from '../common';
import { TemplateCodegenContext, createTemplateCodegenContext } from '../template/context';
import { forEachInterpolationSegment } from '../template/interpolation';
+import { generateStyleScopedClasses } from '../template/styleScopedClasses';
import type { ScriptCodegenContext } from './context';
import { codeFeatures, type ScriptCodegenOptions } from './index';
import { generateInternalComponent } from './internalComponent';
-import { generateStyleScopedClasses } from '../template/styleScopedClasses';
-
-export function* generateTemplate(
- options: ScriptCodegenOptions,
- ctx: ScriptCodegenContext,
- isClassComponent: boolean
-): Generator {
- ctx.generatedTemplate = true;
- if (!options.vueCompilerOptions.skipTemplateCodegen) {
- if (isClassComponent) {
- yield `__VLS_template = (() => {${newLine}`;
- }
- else {
- yield `const __VLS_template = (() => {${newLine}`;
- }
- const templateCodegenCtx = createTemplateCodegenContext({ scriptSetupBindingNames: new Set(), edited: options.edited });
- yield `const __VLS_template_return = () => {${newLine}`;
- yield* generateCtx(options, isClassComponent);
- yield* generateTemplateContext(options, templateCodegenCtx);
- yield* generateExportOptions(options);
- yield* generateConstNameOption(options);
- yield `}${endOfLine}`;
- yield* generateInternalComponent(options, ctx, templateCodegenCtx);
- yield `return __VLS_template_return${endOfLine}`;
- yield `})()${endOfLine}`;
+export function* generateTemplateCtx(options: ScriptCodegenOptions, isClassComponent: boolean): Generator {
+ const types = [];
+ if (isClassComponent) {
+ types.push(`typeof this`);
}
else {
- yield `function __VLS_template() {${newLine}`;
- const templateUsageVars = [...getTemplateUsageVars(options, ctx)];
- yield `// @ts-ignore${newLine}`;
- yield `[${templateUsageVars.join(', ')}]${newLine}`;
- yield `return { slots: {}, refs: {}, attrs: {} }${endOfLine}`;
- yield `}${newLine}`;
+ types.push(`InstanceType<__VLS_PickNotAny {}>>`);
}
+ if (options.vueCompilerOptions.petiteVueExtensions.some(ext => options.fileBaseName.endsWith(ext))) {
+ types.push(`typeof globalThis`);
+ }
+ if (options.sfc.styles.some(style => style.module)) {
+ types.push(`__VLS_StyleModules`);
+ }
+ yield `let __VLS_ctx!: ${types.join(' & ')}${endOfLine}`;
}
-function* generateExportOptions(options: ScriptCodegenOptions): Generator {
- yield newLine;
- yield `const __VLS_componentsOption = `;
+export function* generateTemplateComponents(options: ScriptCodegenOptions): Generator {
+ const exps: Code[] = [];
+
if (options.sfc.script && options.scriptRanges?.exportDefault?.componentsOption) {
- const componentsOption = options.scriptRanges.exportDefault.componentsOption;
- yield [
+ const { componentsOption } = options.scriptRanges.exportDefault;
+ exps.push([
options.sfc.script.content.substring(componentsOption.start, componentsOption.end),
'script',
componentsOption.start,
codeFeatures.navigation,
- ];
- }
- else {
- yield `{}`;
+ ]);
}
- yield endOfLine;
-}
-function* generateConstNameOption(options: ScriptCodegenOptions): Generator {
+ let nameType: Code | undefined;
if (options.sfc.script && options.scriptRanges?.exportDefault?.nameOption) {
- const nameOption = options.scriptRanges.exportDefault.nameOption;
- yield `const __VLS_name = `;
- yield `${options.sfc.script.content.substring(nameOption.start, nameOption.end)} as const`;
- yield endOfLine;
+ const { nameOption } = options.scriptRanges.exportDefault;
+ nameType = options.sfc.script.content.substring(nameOption.start, nameOption.end);
}
else if (options.sfc.scriptSetup) {
yield `let __VLS_name!: '${options.scriptSetupRanges?.options.name ?? options.fileBaseName.substring(0, options.fileBaseName.lastIndexOf('.'))}'${endOfLine}`;
+ nameType = 'typeof __VLS_name';
}
- else {
- yield `const __VLS_name = undefined${endOfLine}`;
+ if (nameType) {
+ exps.push(`{} as {
+ [K in ${nameType}]: typeof __VLS_internalComponent
+ & (new () => {
+ ${getSlotsPropertyName(options.vueCompilerOptions.target)}: typeof ${options.scriptSetupRanges?.slots?.name ?? '__VLS_slots'}
+ })
+ }`);
+ }
+
+ exps.push(`{} as NonNullable`);
+ exps.push(`{} as __VLS_GlobalComponents`);
+ exps.push(`{} as typeof __VLS_ctx`);
+
+ yield `const __VLS_components = {${newLine}`;
+ for (const type of exps) {
+ yield `...`;
+ yield type;
+ yield `,${newLine}`;
}
+ yield `}${endOfLine}`;
}
-function* generateCtx(
+export function* generateTemplate(
options: ScriptCodegenOptions,
+ ctx: ScriptCodegenContext,
isClassComponent: boolean
): Generator {
- yield `let __VLS_ctx!: `;
- if (options.vueCompilerOptions.petiteVueExtensions.some(ext => options.fileBaseName.endsWith(ext))) {
- yield `typeof globalThis & `;
- }
- if (!isClassComponent) {
- yield `InstanceType<__VLS_PickNotAny {}>>`;
+ ctx.generatedTemplate = true;
+
+ if (!options.vueCompilerOptions.skipTemplateCodegen) {
+ const templateCodegenCtx = createTemplateCodegenContext({ scriptSetupBindingNames: new Set(), edited: options.edited });
+ yield* generateTemplateCtx(options, isClassComponent);
+ yield* generateTemplateComponents(options);
+ yield* generateTemplateBody(options, templateCodegenCtx);
+ yield* generateInternalComponent(options, ctx, templateCodegenCtx);
}
else {
- yield `typeof this`;
- }
- /* CSS Module */
- if (options.sfc.styles.some(style => style.module)) {
- yield ` & __VLS_StyleModules`;
+ const templateUsageVars = [...getTemplateUsageVars(options, ctx)];
+ yield `// @ts-ignore${newLine}`;
+ yield `[${templateUsageVars.join(', ')}]${newLine}`;
+ yield `const __VLS_templateResult { slots: {}, refs: {}, attrs: {} }${endOfLine}`;
}
- yield endOfLine;
}
-function* generateTemplateContext(
+function* generateTemplateBody(
options: ScriptCodegenOptions,
templateCodegenCtx: TemplateCodegenContext
): Generator {
- /* Components */
- yield `/* Components */${newLine}`;
- yield `let __VLS_otherComponents!: NonNullable & typeof __VLS_componentsOption${endOfLine}`;
- yield `let __VLS_own!: __VLS_SelfComponent { ${getSlotsPropertyName(options.vueCompilerOptions.target)}: typeof ${options.scriptSetupRanges?.slots?.name ?? '__VLS_slots'} })>${endOfLine}`;
- yield `let __VLS_localComponents!: typeof __VLS_otherComponents & Omit${endOfLine}`;
- yield `let __VLS_components!: typeof __VLS_localComponents & __VLS_GlobalComponents & typeof __VLS_ctx${endOfLine}`; // for html completion, TS references...
-
- /* Style Scoped */
const firstClasses = new Set();
- yield `/* Style Scoped */${newLine}`;
yield `let __VLS_styleScopedClasses!: {}`;
for (let i = 0; i < options.sfc.styles.length; i++) {
const style = options.sfc.styles[i];
@@ -155,7 +140,7 @@ function* generateTemplateContext(
}
}
- yield `return {${newLine}`;
+ yield `const __VLS_templateResult = {`;
yield `slots: ${options.scriptSetupRanges?.slots.name ?? '__VLS_slots'},${newLine}`;
yield `refs: __VLS_refs as __VLS_PickRefsExpose,${newLine}`;
yield `attrs: {} as Partial,${newLine}`;
diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts
index b6aa1f43ce..c68a820da3 100644
--- a/packages/language-core/lib/codegen/template/index.ts
+++ b/packages/language-core/lib/codegen/template/index.ts
@@ -120,7 +120,7 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator `"${name}"`)
.join(', ');
diff --git a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap
index d708893965..878dcd52ac 100644
--- a/packages/tsc/tests/__snapshots__/dts.spec.ts.snap
+++ b/packages/tsc/tests/__snapshots__/dts.spec.ts.snap
@@ -634,24 +634,30 @@ export {};
`;
exports[`vue-tsc-dts > Input: template-slots/component.vue, Output: template-slots/component.vue.d.ts 1`] = `
-"declare const __VLS_template: () => {
+"declare var __VLS_0: {};
+declare var __VLS_1: {
+ num: number;
+};
+declare var __VLS_2: {
+ str: string;
+};
+declare var __VLS_3: {
+ num: number;
+ str: string;
+};
+declare var __VLS_inheritedAttrs: {};
+declare const __VLS_refs: {};
+declare const __VLS_templateResult: {
slots: {
- "no-bind"?(_: {}): any;
- default?(_: {
- num: number;
- }): any;
- "named-slot"?(_: {
- str: string;
- }): any;
- vbind?(_: {
- num: number;
- str: string;
- }): any;
+ "no-bind"?(_: typeof __VLS_0): any;
+ default?(_: typeof __VLS_1): any;
+ "named-slot"?(_: typeof __VLS_2): any;
+ vbind?(_: typeof __VLS_3): any;
};
- refs: __VLS_PickRefsExpose<{}>;
- attrs: Partial<{}>;
+ refs: __VLS_PickRefsExpose;
+ attrs: Partial;
};
-type __VLS_Slots = ReturnType['slots'];
+type __VLS_Slots = typeof __VLS_templateResult['slots'];
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly>, {}, {}>;
declare const _default: __VLS_WithTemplateSlots;
export default _default;
@@ -665,7 +671,9 @@ type __VLS_WithTemplateSlots = T & {
exports[`vue-tsc-dts > Input: template-slots/component-define-slots.vue, Output: template-slots/component-define-slots.vue.d.ts 1`] = `
"import { VNode } from 'vue';
-declare const __VLS_template: () => {
+declare var __VLS_inheritedAttrs: {};
+declare const __VLS_refs: {};
+declare const __VLS_templateResult: {
slots: Readonly<{
default: (props: {
num: number;
@@ -691,10 +699,10 @@ declare const __VLS_template: () => {
}) => VNode[];
'no-bind': () => VNode[];
};
- refs: __VLS_PickRefsExpose<{}>;
- attrs: Partial<{}>;
+ refs: __VLS_PickRefsExpose;
+ attrs: Partial;
};
-type __VLS_Slots = ReturnType['slots'];
+type __VLS_Slots = typeof __VLS_templateResult['slots'];
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly>, {}, {}>;
declare const _default: __VLS_WithTemplateSlots;
export default _default;
@@ -707,7 +715,9 @@ type __VLS_WithTemplateSlots = T & {
`;
exports[`vue-tsc-dts > Input: template-slots/component-destructuring.vue, Output: template-slots/component-destructuring.vue.d.ts 1`] = `
-"declare const __VLS_template: () => {
+"declare var __VLS_inheritedAttrs: {};
+declare const __VLS_refs: {};
+declare const __VLS_templateResult: {
slots: Readonly<{
bottom: (props: {
num: number;
@@ -717,10 +727,10 @@ exports[`vue-tsc-dts > Input: template-slots/component-destructuring.vue, Output
num: number;
}) => any[];
};
- refs: __VLS_PickRefsExpose<{}>;
- attrs: Partial<{}>;
+ refs: __VLS_PickRefsExpose;
+ attrs: Partial;
};
-type __VLS_Slots = ReturnType['slots'];
+type __VLS_Slots = typeof __VLS_templateResult['slots'];
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly>, {}, {}>;
declare const _default: __VLS_WithTemplateSlots;
export default _default;
@@ -733,24 +743,30 @@ type __VLS_WithTemplateSlots = T & {
`;
exports[`vue-tsc-dts > Input: template-slots/component-no-script.vue, Output: template-slots/component-no-script.vue.d.ts 1`] = `
-"declare const __VLS_template: () => {
+"declare var __VLS_0: {};
+declare var __VLS_1: {
+ num: number;
+};
+declare var __VLS_2: {
+ str: string;
+};
+declare var __VLS_3: {
+ num: number;
+ str: string;
+};
+declare var __VLS_inheritedAttrs: {};
+declare const __VLS_refs: {};
+declare const __VLS_templateResult: {
slots: {
- "no-bind"?(_: {}): any;
- default?(_: {
- num: number;
- }): any;
- "named-slot"?(_: {
- str: string;
- }): any;
- vbind?(_: {
- num: number;
- str: string;
- }): any;
+ "no-bind"?(_: typeof __VLS_0): any;
+ default?(_: typeof __VLS_1): any;
+ "named-slot"?(_: typeof __VLS_2): any;
+ vbind?(_: typeof __VLS_3): any;
};
- refs: __VLS_PickRefsExpose<{}>;
- attrs: Partial<{}>;
+ refs: __VLS_PickRefsExpose;
+ attrs: Partial;
};
-type __VLS_Slots = ReturnType['slots'];
+type __VLS_Slots = typeof __VLS_templateResult['slots'];
declare const __VLS_component: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly>, {}, {}>;
declare const _default: __VLS_WithTemplateSlots;
export default _default;
From a162f043abcb54af9c372b5d82b970bb0f0a2fbd Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Thu, 29 Aug 2024 06:36:24 +0800
Subject: [PATCH 11/93] refactor(component-meta): remove deprecated functions
and exports
---
packages/component-meta/index.ts | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/packages/component-meta/index.ts b/packages/component-meta/index.ts
index ec0300e6d1..f38e447dfb 100644
--- a/packages/component-meta/index.ts
+++ b/packages/component-meta/index.ts
@@ -4,16 +4,6 @@ import type { MetaCheckerOptions } from './lib/types';
export * from './lib/types';
-/**
- * @deprecated Use `createCheckerByJson` instead.
- */
-export const createComponentMetaCheckerByJsonConfig = createCheckerByJson;
-
-/**
- * @deprecated Use `createChecker` instead.
- */
-export const createComponentMetaChecker = createChecker;
-
export function createCheckerByJson(
rootPath: string,
json: any,
From 38c1e48eca720e0c8faf892d1aff8b44fede3951 Mon Sep 17 00:00:00 2001
From: Johnson Chu
Date: Thu, 29 Aug 2024 07:09:22 +0800
Subject: [PATCH 12/93] refactor: write real files to FS for shared global
types (#4736)
---
package.json | 16 +-
packages/component-meta/lib/base.ts | 46 ++--
packages/language-core/index.ts | 7 +-
.../language-core/lib/codegen/globalTypes.ts | 125 +++++++++++
.../language-core/lib/codegen/localTypes.ts | 148 +++++++++++++
.../lib/codegen/script/component.ts | 8 +-
.../lib/codegen/script/context.ts | 120 +---------
.../lib/codegen/script/globalTypes.ts | 146 -------------
.../language-core/lib/codegen/script/index.ts | 16 +-
.../lib/codegen/script/scriptSetup.ts | 12 +-
.../lib/codegen/script/template.ts | 15 +-
.../lib/codegen/template/objectProperty.ts | 4 +-
packages/language-core/lib/languagePlugin.ts | 91 +-------
packages/language-core/lib/plugins/vue-tsx.ts | 1 -
packages/language-core/lib/types.ts | 1 -
.../schemas/vue-tsconfig.schema.json | 2 +-
packages/language-server/lib/initialize.ts | 48 +++-
packages/language-server/node.ts | 17 +-
.../language-server/tests/completions.spec.ts | 14 --
.../language-server/tests/definitions.spec.ts | 12 -
.../language-server/tests/inlayHints.spec.ts | 13 --
.../language-server/tests/references.spec.ts | 12 -
.../language-server/tests/renaming.spec.ts | 15 --
.../language-service/tests/utils/format.ts | 9 +-
packages/tsc/index.ts | 32 ++-
.../tsc/tests/__snapshots__/dts.spec.ts.snap | 53 +++--
packages/tsc/tests/dts.spec.ts | 25 ++-
packages/typescript-plugin/index.ts | 42 +++-
pnpm-lock.yaml | 206 +++++++++---------
29 files changed, 608 insertions(+), 648 deletions(-)
create mode 100644 packages/language-core/lib/codegen/globalTypes.ts
create mode 100644 packages/language-core/lib/codegen/localTypes.ts
delete mode 100644 packages/language-core/lib/codegen/script/globalTypes.ts
diff --git a/package.json b/package.json
index 2e95edd2db..8ca48ee9a7 100644
--- a/package.json
+++ b/package.json
@@ -32,14 +32,14 @@
},
"pnpm": {
"overrides": {
- "@volar/kit": "https://pkg.pr.new/volarjs/volar.js/@volar/kit@28cbdee",
- "@volar/language-core": "https://pkg.pr.new/volarjs/volar.js/@volar/language-core@28cbdee",
- "@volar/language-server": "https://pkg.pr.new/volarjs/volar.js/@volar/language-server@28cbdee",
- "@volar/language-service": "https://pkg.pr.new/volarjs/volar.js/@volar/language-service@28cbdee",
- "@volar/source-map": "https://pkg.pr.new/volarjs/volar.js/@volar/source-map@28cbdee",
- "@volar/test-utils": "https://pkg.pr.new/volarjs/volar.js/@volar/test-utils@28cbdee",
- "@volar/typescript": "https://pkg.pr.new/volarjs/volar.js/@volar/typescript@28cbdee",
- "@volar/vscode": "https://pkg.pr.new/volarjs/volar.js/@volar/vscode@28cbdee",
+ "@volar/kit": "https://pkg.pr.new/volarjs/volar.js/@volar/kit@0e1be44",
+ "@volar/language-core": "https://pkg.pr.new/volarjs/volar.js/@volar/language-core@0e1be44",
+ "@volar/language-server": "https://pkg.pr.new/volarjs/volar.js/@volar/language-server@0e1be44",
+ "@volar/language-service": "https://pkg.pr.new/volarjs/volar.js/@volar/language-service@0e1be44",
+ "@volar/source-map": "https://pkg.pr.new/volarjs/volar.js/@volar/source-map@0e1be44",
+ "@volar/test-utils": "https://pkg.pr.new/volarjs/volar.js/@volar/test-utils@0e1be44",
+ "@volar/typescript": "https://pkg.pr.new/volarjs/volar.js/@volar/typescript@0e1be44",
+ "@volar/vscode": "https://pkg.pr.new/volarjs/volar.js/@volar/vscode@0e1be44",
"volar-service-typescript": "https://pkg.pr.new/volarjs/services/volar-service-typescript@177b9ed",
"inquirer": "9.2.23"
}
diff --git a/packages/component-meta/lib/base.ts b/packages/component-meta/lib/base.ts
index e71738e5e4..cda971c749 100644
--- a/packages/component-meta/lib/base.ts
+++ b/packages/component-meta/lib/base.ts
@@ -1,19 +1,19 @@
+import { TypeScriptProjectHost, createLanguageServiceHost, resolveFileLanguageId } from '@volar/typescript';
import * as vue from '@vue/language-core';
-import type * as ts from 'typescript';
import * as path from 'path-browserify';
+import type * as ts from 'typescript';
import { code as typeHelpersCode } from 'vue-component-type-helpers';
import { code as vue2TypeHelpersCode } from 'vue-component-type-helpers/vue2';
-import { TypeScriptProjectHost, createLanguageServiceHost, resolveFileLanguageId } from '@volar/typescript';
import type {
- MetaCheckerOptions,
ComponentMeta,
+ Declaration,
EventMeta,
ExposeMeta,
+ MetaCheckerOptions,
PropertyMeta,
PropertyMetaSchema,
- SlotMeta,
- Declaration
+ SlotMeta
} from './types';
export * from './types';
@@ -83,16 +83,11 @@ export function baseCreate(
];
};
- const vueLanguagePlugin = vue.createVueLanguagePlugin2(
+ const vueLanguagePlugin = vue.createVueLanguagePlugin(
ts,
- id => id,
- vue.createRootFileChecker(
- projectHost.getProjectVersion ? () => projectHost.getProjectVersion!() : undefined,
- () => projectHost.getScriptFileNames(),
- ts.sys.useCaseSensitiveFileNames
- ),
projectHost.getCompilationSettings(),
- commandLine.vueOptions
+ commandLine.vueOptions,
+ id => id
);
const language = vue.createLanguage(
[
@@ -140,6 +135,31 @@ export function baseCreate(
const { languageServiceHost } = createLanguageServiceHost(ts, ts.sys, language, s => s, projectHost);
const tsLs = ts.createLanguageService(languageServiceHost);
+ const fileExists = languageServiceHost.fileExists.bind(languageServiceHost);
+ const getScriptSnapshot = languageServiceHost.getScriptSnapshot.bind(languageServiceHost);
+ const globalTypesName = `__globalTypes_${commandLine.vueOptions.target}_${commandLine.vueOptions.strictTemplates}.d.ts`;
+ const snapshots = new Map();
+ languageServiceHost.fileExists = path => {
+ if (path.endsWith(globalTypesName)) {
+ return true;
+ }
+ return fileExists(path);
+ };
+ languageServiceHost.getScriptSnapshot = path => {
+ if (path.endsWith(globalTypesName)) {
+ if (!snapshots.has(path)) {
+ const contents = vue.generateGlobalTypes(commandLine.vueOptions.lib, commandLine.vueOptions.target, commandLine.vueOptions.strictTemplates);
+ snapshots.set(path, {
+ getText: (start, end) => contents.substring(start, end),
+ getLength: () => contents.length,
+ getChangeRange: () => undefined,
+ });
+ }
+ return snapshots.get(path)!;
+ }
+ return getScriptSnapshot(path);
+ };
+
if (checkerOptions.forceUseTs) {
const getScriptKind = languageServiceHost.getScriptKind?.bind(languageServiceHost);
languageServiceHost.getScriptKind = fileName => {
diff --git a/packages/language-core/index.ts b/packages/language-core/index.ts
index d539d6591c..2ca1dc11cc 100644
--- a/packages/language-core/index.ts
+++ b/packages/language-core/index.ts
@@ -1,15 +1,16 @@
+export * from './lib/codegen/globalTypes';
export * from './lib/codegen/template';
export * from './lib/languagePlugin';
export * from './lib/parsers/scriptSetupRanges';
export * from './lib/plugins';
-export * from './lib/virtualFile/vueFile';
export * from './lib/types';
-export * from './lib/utils/ts';
export * from './lib/utils/parseSfc';
+export * from './lib/utils/ts';
+export * from './lib/virtualFile/vueFile';
export * as scriptRanges from './lib/parsers/scriptRanges';
-export * from './lib/utils/shared';
export { tsCodegen } from './lib/plugins/vue-tsx';
+export * from './lib/utils/shared';
export * from '@volar/language-core';
export type * as CompilerDOM from '@vue/compiler-dom';
diff --git a/packages/language-core/lib/codegen/globalTypes.ts b/packages/language-core/lib/codegen/globalTypes.ts
new file mode 100644
index 0000000000..19689701d5
--- /dev/null
+++ b/packages/language-core/lib/codegen/globalTypes.ts
@@ -0,0 +1,125 @@
+import { getSlotsPropertyName } from '../utils/shared';
+
+export function generateGlobalTypes(lib: string, target: number, strictTemplates: boolean) {
+ const fnPropsType = `(K extends { $props: infer Props } ? Props : any)${strictTemplates ? '' : ' & Record'}`;
+ return `
+const __VLS_globalComponents = { ...{} as import('${lib}').GlobalComponents };
+
+declare const __VLS_intrinsicElements: __VLS_IntrinsicElements;
+declare const __VLS_directiveBindingRestFields = { instance: null, oldValue: null, modifiers: null as any, dir: null as any };
+
+type __VLS_IntrinsicElements = ${(
+ target >= 3.3
+ ? `import('${lib}/jsx-runtime').JSX.IntrinsicElements;`
+ : `globalThis.JSX.IntrinsicElements;`
+ )}
+type __VLS_Element = ${(
+ target >= 3.3
+ ? `import('${lib}/jsx-runtime').JSX.Element;`
+ : `globalThis.JSX.Element;`
+ )}
+type __VLS_GlobalComponents = ${(
+ target >= 3.5
+ ? `void extends typeof __VLS_globalComponents ? {} : typeof __VLS_globalComponents;`
+ : `(void extends typeof __VLS_globalComponents ? {} : typeof __VLS_globalComponents) & Pick;`
+ )}
+type __VLS_IsAny = 0 extends 1 & T ? true : false;
+type __VLS_PickNotAny = __VLS_IsAny extends true ? B : A;
+type __VLS_unknownDirective = (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
+type __VLS_WithComponent =
+ N1 extends keyof LocalComponents ? N1 extends N0 ? Pick : { [K in N0]: LocalComponents[N1] } :
+ N2 extends keyof LocalComponents ? N2 extends N0 ? Pick : { [K in N0]: LocalComponents[N2] } :
+ N3 extends keyof LocalComponents ? N3 extends N0 ? Pick : { [K in N0]: LocalComponents[N3] } :
+ N1 extends keyof __VLS_GlobalComponents ? N1 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N1] } :
+ N2 extends keyof __VLS_GlobalComponents ? N2 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N2] } :
+ N3 extends keyof __VLS_GlobalComponents ? N3 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N3] } :
+ ${strictTemplates ? '{}' : '{ [K in N0]: unknown }'}
+type __VLS_FunctionalComponentProps =
+ '__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: { props?: infer P } } ? NonNullable : never
+ : T extends (props: infer P, ...args: any) => any ? P :
+ {};
+type __VLS_IsFunction = K extends keyof T
+ ? __VLS_IsAny extends false
+ ? unknown extends T[K]
+ ? false
+ : true
+ : false
+ : false;
+// fix https://github.com/vuejs/language-tools/issues/926
+type __VLS_UnionToIntersection = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
+type __VLS_OverloadUnionInner = U & T extends (...args: infer A) => infer R
+ ? U extends T
+ ? never
+ : __VLS_OverloadUnionInner & U & ((...args: A) => R)> | ((...args: A) => R)
+ : never;
+type __VLS_OverloadUnion = Exclude<
+ __VLS_OverloadUnionInner<(() => never) & T>,
+ T extends () => never ? never : () => never
+>;
+type __VLS_ConstructorOverloads = __VLS_OverloadUnion extends infer F
+ ? F extends (event: infer E, ...args: infer A) => any
+ ? { [K in E & string]: (...args: A) => void; }
+ : never
+ : never;
+type __VLS_NormalizeEmits = __VLS_PrettifyGlobal<
+ __VLS_UnionToIntersection<
+ __VLS_ConstructorOverloads & {
+ [K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
+ }
+ >
+>;
+type __VLS_PrettifyGlobal = { [K in keyof T]: T[K]; } & {};
+
+declare function __VLS_getVForSourceType(source: number): [number, number, number][];
+declare function __VLS_getVForSourceType(source: string): [string, number, number][];
+declare function __VLS_getVForSourceType(source: T): [
+ item: T[number],
+ key: number,
+ index: number,
+][];
+declare function __VLS_getVForSourceType }>(source: T): [
+ item: T extends { [Symbol.iterator](): Iterator } ? T1 : never,
+ key: number,
+ index: undefined,
+][];
+// #3845
+declare function __VLS_getVForSourceType }>(source: T): [
+ item: number | (Exclude extends { [Symbol.iterator](): Iterator } ? T1 : never),
+ key: number,
+ index: undefined,
+][];
+declare function __VLS_getVForSourceType(source: T): [
+ item: T[keyof T],
+ key: keyof T,
+ index: number,
+][];
+// @ts-ignore
+declare function __VLS_getSlotParams(slot: T): Parameters<__VLS_PickNotAny, (...args: any[]) => any>>;
+// @ts-ignore
+declare function __VLS_getSlotParam(slot: T): Parameters<__VLS_PickNotAny, (...args: any[]) => any>>[0];
+declare function __VLS_directiveAsFunction(dir: T): T extends (...args: any) => any
+ ? T | __VLS_unknownDirective
+ : NonNullable<(T & Record)['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>;
+declare function __VLS_withScope(ctx: T, scope: K): ctx is T & K;
+declare function __VLS_makeOptional(t: T): { [K in keyof T]?: T[K] };
+declare function __VLS_nonNullable(t: T): T extends null | undefined ? never : T;
+declare function __VLS_asFunctionalComponent any ? InstanceType : unknown>(t: T, instance?: K):
+ T extends new (...args: any) => any
+ ? (props: ${fnPropsType}, ctx?: any) => __VLS_Element & { __ctx?: {
+ attrs?: any,
+ slots?: K extends { ${getSlotsPropertyName(target)}: infer Slots } ? Slots : any,
+ emit?: K extends { $emit: infer Emit } ? Emit : any
+ } & { props?: ${fnPropsType}; expose?(exposed: K): void; } }
+ : T extends () => any ? (props: {}, ctx?: any) => ReturnType
+ : T extends (...args: any) => any ? T
+ : (_: {}${strictTemplates ? '' : ' & Record'}, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: {}${strictTemplates ? '' : ' & Record'} } };
+declare function __VLS_elementAsFunction(tag: T, endTag?: T): (_: T${strictTemplates ? '' : ' & Record'}) => void;
+declare function __VLS_functionalComponentArgsRest any>(t: T): Parameters['length'] extends 2 ? [any] : [];
+declare function __VLS_pickFunctionalComponentCtx(comp: T, compInstance: K): NonNullable<__VLS_PickNotAny<
+ '__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
+ , T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
+>>;
+declare function __VLS_normalizeSlot(s: S): S extends () => infer R ? (props: {}) => R : S;
+declare function __VLS_tryAsConstant(t: T): T;
+`;
+};
diff --git a/packages/language-core/lib/codegen/localTypes.ts b/packages/language-core/lib/codegen/localTypes.ts
new file mode 100644
index 0000000000..e244f16f0f
--- /dev/null
+++ b/packages/language-core/lib/codegen/localTypes.ts
@@ -0,0 +1,148 @@
+import type * as ts from 'typescript';
+import { VueCompilerOptions } from '../types';
+import { getSlotsPropertyName } from '../utils/shared';
+import { endOfLine } from './common';
+
+export function getLocalTypesGenerator(compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions) {
+ const used = new Set();
+
+ const OmitKeepDiscriminatedUnion = defineHelper(
+ `__VLS_OmitKeepDiscriminatedUnion`,
+ () => `
+type __VLS_OmitKeepDiscriminatedUnion = T extends any
+ ? Pick>
+ : never;
+`.trimStart()
+ );
+ const WithDefaults = defineHelper(
+ `__VLS_WithDefaults`,
+ () => `
+type __VLS_WithDefaults = {
+ [K in keyof Pick
]: K extends keyof D
+ ? ${PrettifyLocal.name}
+ : P[K]
+};
+`.trimStart()
+ );
+ const PrettifyLocal = defineHelper(
+ `__VLS_PrettifyLocal`,
+ () => `type __VLS_PrettifyLocal = { [K in keyof T]: T[K]; } & {}${endOfLine}`
+ );
+ const WithTemplateSlots = defineHelper(
+ `__VLS_WithTemplateSlots`,
+ () => `
+type __VLS_WithTemplateSlots = T & {
+ new(): {
+ ${getSlotsPropertyName(vueCompilerOptions.target)}: S;
+ ${vueCompilerOptions.jsxSlots ? `$props: ${PropsChildren.name};` : ''}
+ }
+};
+`.trimStart()
+ );
+ const PropsChildren = defineHelper(
+ `__VLS_PropsChildren`,
+ () => `
+type __VLS_PropsChildren = {
+ [K in keyof (
+ boolean extends (
+ // @ts-ignore
+ JSX.ElementChildrenAttribute extends never
+ ? true
+ : false
+ )
+ ? never
+ // @ts-ignore
+ : JSX.ElementChildrenAttribute
+ )]?: S;
+};
+`.trimStart()
+ );
+ const TypePropsToOption = defineHelper(
+ `__VLS_TypePropsToOption`,
+ () => compilerOptions.exactOptionalPropertyTypes ?
+ `
+type __VLS_TypePropsToOption = {
+ [K in keyof T]-?: {} extends Pick
+ ? { type: import('${vueCompilerOptions.lib}').PropType }
+ : { type: import('${vueCompilerOptions.lib}').PropType, required: true }
+};
+`.trimStart() :
+ `
+type __VLS_NonUndefinedable = T extends undefined ? never : T;
+type __VLS_TypePropsToOption = {
+ [K in keyof T]-?: {} extends Pick
+ ? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable> }
+ : { type: import('${vueCompilerOptions.lib}').PropType, required: true }
+};
+`.trimStart()
+ );
+ const OmitIndexSignature = defineHelper(
+ `__VLS_OmitIndexSignature`,
+ () => `type __VLS_OmitIndexSignature = { [K in keyof T as {} extends Record ? never : K]: T[K]; }${endOfLine}`
+ );
+ const PickRefsExpose = defineHelper(
+ `__VLS_PickRefsExpose`,
+ () => `
+type __VLS_PickRefsExpose = T extends object
+ ? { [K in keyof T]: (T[K] extends any[]
+ ? Parameters[0][]
+ : T[K] extends { expose?: (exposed: infer E) => void }
+ ? E
+ : T[K]) | null }
+ : never;
+`.trimStart()
+ );
+
+ const helpers = {
+ [PrettifyLocal.name]: PrettifyLocal,
+ [OmitKeepDiscriminatedUnion.name]: OmitKeepDiscriminatedUnion,
+ [WithDefaults.name]: WithDefaults,
+ [WithTemplateSlots.name]: WithTemplateSlots,
+ [PropsChildren.name]: PropsChildren,
+ [TypePropsToOption.name]: TypePropsToOption,
+ [OmitIndexSignature.name]: OmitIndexSignature,
+ [PickRefsExpose.name]: PickRefsExpose,
+ };
+ used.clear();
+
+ return {
+ generate,
+ getUsedNames() {
+ return used;
+ },
+ get PrettifyLocal() { return PrettifyLocal.name; },
+ get OmitKeepDiscriminatedUnion() { return OmitKeepDiscriminatedUnion.name; },
+ get WithDefaults() { return WithDefaults.name; },
+ get WithTemplateSlots() { return WithTemplateSlots.name; },
+ get PropsChildren() { return PropsChildren.name; },
+ get TypePropsToOption() { return TypePropsToOption.name; },
+ get OmitIndexSignature() { return OmitIndexSignature.name; },
+ get PickRefsExpose() { return PickRefsExpose.name; },
+ };
+
+ function* generate(names: string[]) {
+ const generated = new Set();
+ while (names.length) {
+ used.clear();
+ for (const name of names) {
+ if (generated.has(name)) {
+ continue;
+ }
+ const helper = helpers[name as keyof typeof helpers];
+ yield helper.generate();
+ generated.add(name);
+ }
+ names = [...used].filter(name => !generated.has(name));
+ }
+ }
+
+ function defineHelper(name: string, generate: () => string) {
+ return {
+ get name() {
+ used.add(name);
+ return name;
+ },
+ generate,
+ };
+ }
+}
diff --git a/packages/language-core/lib/codegen/script/component.ts b/packages/language-core/lib/codegen/script/component.ts
index 457ba0c133..929d1f370d 100644
--- a/packages/language-core/lib/codegen/script/component.ts
+++ b/packages/language-core/lib/codegen/script/component.ts
@@ -131,8 +131,8 @@ export function* generatePropsOption(
if (ctx.generatedPropsType) {
optionExpCodes.push([
`{} as `,
- scriptSetupRanges.props.withDefaults?.arg ? `${ctx.helperTypes.WithDefaults.name}<` : '',
- `${ctx.helperTypes.TypePropsToOption.name}<__VLS_PublicProps>`,
+ scriptSetupRanges.props.withDefaults?.arg ? `${ctx.localTypes.WithDefaults}<` : '',
+ `${ctx.localTypes.TypePropsToOption}<__VLS_PublicProps>`,
scriptSetupRanges.props.withDefaults?.arg ? `, typeof __VLS_withDefaultsArg>` : '',
].join(''));
typeOptionExpCodes.push(`{} as __VLS_PublicProps`);
@@ -146,8 +146,8 @@ export function* generatePropsOption(
if (hasEmitsOption) {
attrsType = `Omit<${attrsType}, \`on\${string}\`>`;
}
- const propsType = `__VLS_PickNotAny<${ctx.helperTypes.OmitIndexSignature.name}<${attrsType}>, {}>`;
- const optionType = `${ctx.helperTypes.TypePropsToOption.name}<${propsType}>`;
+ const propsType = `__VLS_PickNotAny<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>`;
+ const optionType = `${ctx.localTypes.TypePropsToOption}<${propsType}>`;
if (optionExpCodes.length) {
optionExpCodes.unshift(`{} as ${optionType}`);
}
diff --git a/packages/language-core/lib/codegen/script/context.ts b/packages/language-core/lib/codegen/script/context.ts
index 8bb0ad2176..60d30f82ce 100644
--- a/packages/language-core/lib/codegen/script/context.ts
+++ b/packages/language-core/lib/codegen/script/context.ts
@@ -1,6 +1,5 @@
-import { getSlotsPropertyName } from '../../utils/shared';
-import { newLine } from '../common';
import { InlayHintInfo } from '../types';
+import { getLocalTypesGenerator } from '../localTypes';
import type { ScriptCodegenOptions } from './index';
export interface HelperType {
@@ -13,105 +12,7 @@ export interface HelperType {
export type ScriptCodegenContext = ReturnType;
export function createScriptCodegenContext(options: ScriptCodegenOptions) {
- const helperTypes = {
- OmitKeepDiscriminatedUnion: {
- get name() {
- this.used = true;
- return `__VLS_OmitKeepDiscriminatedUnion`;
- },
- get code() {
- return `type __VLS_OmitKeepDiscriminatedUnion = T extends any
- ? Pick>
- : never;`;
- },
- } satisfies HelperType as HelperType,
- WithDefaults: {
- get name() {
- this.used = true;
- return `__VLS_WithDefaults`;
- },
- get code(): string {
- return `type __VLS_WithDefaults = {
- [K in keyof Pick
]: K extends keyof D
- ? ${helperTypes.Prettify.name}
- : P[K]
- };`;
- },
- } satisfies HelperType as HelperType,
- Prettify: {
- get name() {
- this.used = true;
- return `__VLS_Prettify`;
- },
- get code() {
- return `type __VLS_Prettify = { [K in keyof T]: T[K]; } & {};`;
- },
- } satisfies HelperType as HelperType,
- WithTemplateSlots: {
- get name() {
- this.used = true;
- return `__VLS_WithTemplateSlots`;
- },
- get code(): string {
- return `type __VLS_WithTemplateSlots = T & {
- new(): {
- ${getSlotsPropertyName(options.vueCompilerOptions.target)}: S;
- ${options.vueCompilerOptions.jsxSlots ? `$props: ${helperTypes.PropsChildren.name};` : ''}
- }
- };`;
- },
- } satisfies HelperType as HelperType,
- PropsChildren: {
- get name() {
- this.used = true;
- return `__VLS_PropsChildren`;
- },
- get code() {
- return `type __VLS_PropsChildren