diff --git a/packages/language-core/lib/codegen/codeFeatures.ts b/packages/language-core/lib/codegen/codeFeatures.ts index 0baa2d992c..c7143649c7 100644 --- a/packages/language-core/lib/codegen/codeFeatures.ts +++ b/packages/language-core/lib/codegen/codeFeatures.ts @@ -72,6 +72,26 @@ const raw = { navigation: true, completion: true, }, + doNotReportTs2339AndTs2551: { + verification: { + // https://typescript.tv/errors/#ts2339 + // https://typescript.tv/errors/#ts2551 + shouldReport: (_source, code) => String(code) !== '2339' && String(code) !== '2551', + }, + }, + doNotReportTs2353AndTs2561: { + verification: { + // https://typescript.tv/errors/#ts2353 + // https://typescript.tv/errors/#ts2561 + shouldReport: (_source, code) => String(code) !== '2353' && String(code) !== '2561', + }, + }, + doNotReportTs6133: { + verification: { + // https://typescript.tv/errors/#ts6133 + shouldReport: (_source, code) => String(code) !== '6133', + }, + }, } satisfies Record; export const codeFeatures = raw as { diff --git a/packages/language-core/lib/codegen/globalTypes.ts b/packages/language-core/lib/codegen/globalTypes.ts index c03bd3bf49..5851bb1899 100644 --- a/packages/language-core/lib/codegen/globalTypes.ts +++ b/packages/language-core/lib/codegen/globalTypes.ts @@ -1,29 +1,17 @@ import type { VueCompilerOptions } from '../types'; import { getSlotsPropertyName } from '../utils/shared'; -export function getGlobalTypesFileName({ - lib, - target, - checkUnknownProps, - checkUnknownEvents, - checkUnknownComponents, -}: VueCompilerOptions) { +export function getGlobalTypesFileName(options: VueCompilerOptions) { return [ - lib, - target, - checkUnknownProps, - checkUnknownEvents, - checkUnknownComponents, + options.lib, + options.target, + options.checkUnknownProps, ].map(v => (typeof v === 'boolean' ? Number(v) : v)).join('_') + '.d.ts'; } -export function generateGlobalTypes({ - lib, - target, - checkUnknownProps, - checkUnknownEvents, - checkUnknownComponents, -}: VueCompilerOptions) { +export function generateGlobalTypes(options: VueCompilerOptions) { + const { lib, target, checkUnknownProps } = options; + const fnPropsType = `(T extends { $props: infer Props } ? Props : {})${ checkUnknownProps ? '' : ' & Record' }`; @@ -69,7 +57,7 @@ export function generateGlobalTypes({ 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] } : - ${checkUnknownComponents ? '{}' : '{ [K in N0]: unknown }'}; + {}; type __VLS_FunctionalComponentCtx = __VLS_PickNotAny<'__ctx' extends keyof __VLS_PickNotAny ? K extends { __ctx?: infer Ctx } ? NonNullable : never : any , T extends (props: any, ctx: infer Ctx) => any ? Ctx : any @@ -80,12 +68,12 @@ export function generateGlobalTypes({ : {}; type __VLS_FunctionalComponent = (props: ${fnPropsType}, ctx?: any) => __VLS_Element & { __ctx?: { - attrs?: any, - slots?: T extends { ${getSlotsPropertyName(target)}: infer Slots } ? Slots : Record, - emit?: T extends { $emit: infer Emit } ? Emit : {}, - props?: ${fnPropsType}, - expose?: (exposed: T) => void, - } + attrs?: any; + slots?: T extends { ${getSlotsPropertyName(target)}: infer Slots } ? Slots : Record; + emit?: T extends { $emit: infer Emit } ? Emit : {}; + props?: ${fnPropsType}; + expose?: (exposed: T) => void; + }; }; type __VLS_IsFunction = K extends keyof T ? __VLS_IsAny extends false @@ -94,15 +82,19 @@ export function generateGlobalTypes({ : true : false : false; - type __VLS_NormalizeComponentEvent = ( - __VLS_IsFunction extends true - ? Props - : __VLS_IsFunction extends true - ? { [K in onEvent]?: Emits[Event] } - : __VLS_IsFunction extends true - ? { [K in onEvent]?: Emits[CamelizedEvent] } - : Props - )${checkUnknownEvents ? '' : ' & Record'}; + type __VLS_NormalizeComponentEvent< + Props, + Emits, + onEvent extends keyof Props, + Event extends keyof Emits, + CamelizedEvent extends keyof Emits, + > = __VLS_IsFunction extends true + ? Props + : __VLS_IsFunction extends true + ? { [K in onEvent]?: Emits[Event] } + : __VLS_IsFunction extends true + ? { [K in onEvent]?: Emits[CamelizedEvent] } + : Props; // 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 @@ -174,7 +166,7 @@ export function generateGlobalTypes({ : __VLS_FunctionalComponent<{}>; function __VLS_functionalComponentArgsRest any>(t: T): 2 extends Parameters['length'] ? [any] : []; function __VLS_asFunctionalElement(tag: T, endTag?: T): (attrs: T${ - checkUnknownComponents ? '' : ' & Record' + checkUnknownProps ? '' : ' & Record' }) => void; function __VLS_asFunctionalSlot(slot: S): S extends () => infer R ? (props: {}) => R : NonNullable; function __VLS_tryAsConstant(t: T): T; diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts index f5254adbe2..55e28e1b0e 100644 --- a/packages/language-core/lib/codegen/template/element.ts +++ b/packages/language-core/lib/codegen/template/element.ts @@ -152,7 +152,12 @@ export function* generateComponent( yield* generateCanonicalComponentName( node.tag, tagOffsets[0], - ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation, + ctx.resolveCodeFeatures({ + ...codeFeatures.semanticWithoutHighlight, + ...options.vueCompilerOptions.checkUnknownComponents + ? codeFeatures.verification + : codeFeatures.doNotReportTs2339AndTs2551, + }), ); yield `${endOfLine}`; @@ -207,14 +212,7 @@ export function* generateComponent( yield* wrapWith( node.loc.start.offset, node.loc.end.offset, - ctx.resolveCodeFeatures({ - verification: { - shouldReport(_source, code) { - // https://typescript.tv/errors/#ts6133 - return String(code) !== '6133'; - }, - }, - }), + ctx.codeFeatures.doNotReportTs6133, componentVNodeVar, ); yield ` = ${componentFunctionalVar}`; diff --git a/packages/language-core/lib/codegen/template/elementEvents.ts b/packages/language-core/lib/codegen/template/elementEvents.ts index 95cef6fadd..132fbe65a7 100644 --- a/packages/language-core/lib/codegen/template/elementEvents.ts +++ b/packages/language-core/lib/codegen/template/elementEvents.ts @@ -2,6 +2,7 @@ import * as CompilerDOM from '@vue/compiler-dom'; import { camelize, capitalize } from '@vue/shared'; import type * as ts from 'typescript'; import type { Code, VueCodeInformation } from '../../types'; +import { codeFeatures } from '../codeFeatures'; import { combineLastMapping, createTsAst, endOfLine, identifierRegex, newLine } from '../utils'; import { generateCamelized } from '../utils/camelized'; import { wrapWith } from '../utils/wrapWith'; @@ -61,12 +62,12 @@ export function* generateElementEvents( yield `const ${ctx.getInternalVariable()}: __VLS_NormalizeComponentEvent = (${newLine}`; if (prop.name === 'on') { yield `{ `; - yield* generateEventArg(ctx, source, start!, emitPrefix.slice(0, -1), ctx.codeFeatures.navigation); + yield* generateEventArg(options, ctx, source, start!, emitPrefix.slice(0, -1), ctx.codeFeatures.navigation); yield `: {} as any } as typeof ${emitsVar},${newLine}`; } yield `{ `; if (prop.name === 'on') { - yield* generateEventArg(ctx, source, start!, propPrefix.slice(0, -1)); + yield* generateEventArg(options, ctx, source, start!, propPrefix.slice(0, -1)); yield `: `; yield* generateEventExpression(options, ctx, prop); } @@ -80,15 +81,21 @@ export function* generateElementEvents( } export function* generateEventArg( + options: TemplateCodegenOptions, ctx: TemplateCodegenContext, name: string, start: number, directive = 'on', - features: VueCodeInformation = { - ...ctx.codeFeatures.withoutHighlightAndCompletion, - ...ctx.codeFeatures.navigationWithoutRename, - }, + features?: VueCodeInformation, ): Generator { + features ??= ctx.resolveCodeFeatures({ + ...codeFeatures.semanticWithoutHighlight, + ...codeFeatures.navigationWithoutRename, + ...options.vueCompilerOptions.checkUnknownEvents + ? codeFeatures.verification + : codeFeatures.doNotReportTs2353AndTs2561, + }); + if (directive.length) { name = capitalize(name); } diff --git a/packages/language-core/lib/codegen/template/elementProps.ts b/packages/language-core/lib/codegen/template/elementProps.ts index 62dec6978d..57dc63eb40 100644 --- a/packages/language-core/lib/codegen/template/elementProps.ts +++ b/packages/language-core/lib/codegen/template/elementProps.ts @@ -46,7 +46,7 @@ export function* generateElementProps( ) { if (!isComponent) { yield `...{ `; - yield* generateEventArg(ctx, prop.arg.loc.source, prop.arg.loc.start.offset); + yield* generateEventArg(options, ctx, prop.arg.loc.source, prop.arg.loc.start.offset); yield `: `; yield* generateEventExpression(options, ctx, prop); yield `},`; @@ -378,16 +378,9 @@ function getPropsCodeInfo( ): VueCodeInformation { return ctx.resolveCodeFeatures({ ...codeFeatures.withoutHighlightAndCompletion, - verification: strictPropsCheck || { - shouldReport(_source, code) { - // https://typescript.tv/errors/#ts2353 - // https://typescript.tv/errors/#ts2561 - if (String(code) === '2353' || String(code) === '2561') { - return false; - } - return true; - }, - }, + ...strictPropsCheck + ? codeFeatures.verification + : codeFeatures.doNotReportTs2353AndTs2561, }); }