diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d198b80c..95a5a5639 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ## Unreleased -- fix: avoid `` type checking with string literal assignment ([#2725](https://github.com/johnsoncodehk/volar/issues/2725)) +- fix: avoid `` type checking with string literal assignment ([#2725](https://github.com/johnsoncodehk/volar/issues/2725)) - fix: `` reporting false positive error when `strictTemplates` enabled ([#2726](https://github.com/johnsoncodehk/volar/issues/2726)) ([#2723](https://github.com/johnsoncodehk/volar/issues/2723)) - fix: error using custom directive: `Expected 2 arguments, but got 1.` ([#2730](https://github.com/johnsoncodehk/volar/issues/2730)) +- fix: namespaced tag not working without script setup +- fix: component intellisense not working in template if TS version < 5.0 ([#2742](https://github.com/johnsoncodehk/volar/issues/2742)) ## 1.6.0 (2023/4/27) diff --git a/packages/vue-language-core/src/generators/script.ts b/packages/vue-language-core/src/generators/script.ts index ec34aa8a9..9188fe389 100644 --- a/packages/vue-language-core/src/generators/script.ts +++ b/packages/vue-language-core/src/generators/script.ts @@ -13,7 +13,7 @@ import { Sfc } from '../types'; import type { VueCompilerOptions } from '../types'; import { getSlotsPropertyName, getVueLibraryName } from '../utils/shared'; import { walkInterpolationFragment } from '../utils/transform'; -import { genConstructorOverloads } from '../utils/localTypes'; +import * as sharedTypes from '../utils/directorySharedTypes'; import * as muggle from 'muggle-string'; export function generate( @@ -29,10 +29,12 @@ export function generate( htmlGen: ReturnType | undefined, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, - codes: Segment[] = [], - mirrorBehaviorMappings: SourceMaps.Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[] = [], + sharedTypesImport: string, ) { + const codes: Segment[] = []; + const mirrorBehaviorMappings: SourceMaps.Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[] = []; + //#region monkey fix: https://github.com/johnsoncodehk/volar/pull/2113 const sfc = { script: _sfc.script, @@ -135,10 +137,10 @@ export function generate( codes.push('type __VLS_UnionToIntersection = __VLS_Prettify<(U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never>;\n'); usedPrettify = true; if (scriptSetupRanges && scriptSetupRanges.emitsTypeNums !== -1) { - codes.push(genConstructorOverloads('__VLS_ConstructorOverloads', scriptSetupRanges.emitsTypeNums)); + codes.push(sharedTypes.genConstructorOverloads('__VLS_ConstructorOverloads', scriptSetupRanges.emitsTypeNums)); } else { - codes.push(genConstructorOverloads('__VLS_ConstructorOverloads')); + codes.push(sharedTypes.genConstructorOverloads('__VLS_ConstructorOverloads')); } } if (usedHelperTypes.WithTemplateSlots) { @@ -606,13 +608,13 @@ declare function defineProp(value?: T | (() => T), required?: boolean, rest?: // fill $props if (scriptSetupRanges.propsTypeArg) { // NOTE: defineProps is inaccurate for $props - codes.push(`$props: (await import('./__VLS_types.d.ts')).makeOptional(defineProps<`); + codes.push(`$props: (await import('${sharedTypesImport}')).makeOptional(defineProps<`); addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.propsTypeArg.start, scriptSetupRanges.propsTypeArg.end); codes.push(`>()),\n`); } else if (scriptSetupRanges.propsRuntimeArg) { // NOTE: defineProps is inaccurate for $props - codes.push(`$props: (await import('./__VLS_types.d.ts')).makeOptional(defineProps(`); + codes.push(`$props: (await import('${sharedTypesImport}')).makeOptional(defineProps(`); addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.propsRuntimeArg.start, scriptSetupRanges.propsRuntimeArg.end); codes.push(`)),\n`); } @@ -813,13 +815,13 @@ declare function defineProp(value?: T | (() => T), required?: boolean, rest?: codes.push(`let __VLS_ctx!: ${useGlobalThisTypeInCtx ? 'typeof globalThis &' : ''}`); if (sfc.scriptSetup) { - codes.push(`InstanceType {}>> & `); + codes.push(`InstanceType {}>> & `); } - codes.push(`InstanceType {}>> & {\n`); + codes.push(`InstanceType {}>> & {\n`); /* CSS Module */ for (const cssModule of cssModuleClasses) { - codes.push(`${cssModule.style.module}: Record & import('./__VLS_types.d.ts').Prettify<{}`); + codes.push(`${cssModule.style.module}: Record & import('${sharedTypesImport}').Prettify<{}`); for (const classNameRange of cssModule.classNameRanges) { generateCssClassProperty( cssModule.index, @@ -836,8 +838,8 @@ declare function defineProp(value?: T | (() => T), required?: boolean, rest?: /* Components */ codes.push('/* Components */\n'); codes.push(`let __VLS_localComponents!: NonNullable & typeof __VLS_componentsOption & typeof __VLS_ctx;\n`); - codes.push(`let __VLS_otherComponents!: typeof __VLS_localComponents & import('./__VLS_types.d.ts').GlobalComponents;\n`); - codes.push(`let __VLS_own!: import('./__VLS_types.d.ts').SelfComponent { ${getSlotsPropertyName(vueCompilerOptions.target)}: typeof __VLS_slots })>;\n`); + codes.push(`let __VLS_otherComponents!: typeof __VLS_localComponents & import('${sharedTypesImport}').GlobalComponents;\n`); + codes.push(`let __VLS_own!: import('${sharedTypesImport}').SelfComponent { ${getSlotsPropertyName(vueCompilerOptions.target)}: typeof __VLS_slots })>;\n`); codes.push(`let __VLS_components!: typeof __VLS_otherComponents & Omit;\n`); /* Style Scoped */ diff --git a/packages/vue-language-core/src/generators/template.ts b/packages/vue-language-core/src/generators/template.ts index cad50fa33..2a59f11a6 100644 --- a/packages/vue-language-core/src/generators/template.ts +++ b/packages/vue-language-core/src/generators/template.ts @@ -67,6 +67,7 @@ export function generate( sourceLang: string, templateAst: CompilerDOM.RootNode, hasScriptSetupSlots: boolean, + sharedTypesImport: string, cssScopedClasses: string[] = [], ) { @@ -177,7 +178,7 @@ export function generate( const varName = validTsVar.test(tagName) ? tagName : capitalize(camelize(tagName.replace(/:/g, '-'))); codes.push( - `& import('./__VLS_types.d.ts').WithComponent<'${varName}', typeof __VLS_components, `, + `& import('${sharedTypesImport}').WithComponent<'${varName}', typeof __VLS_components, `, // order is important: https://github.com/johnsoncodehk/volar/issues/2010 `"${capitalize(camelize(tagName))}", `, `"${camelize(tagName)}", `, @@ -460,7 +461,7 @@ export function generate( codes.push([leftExpressionText, 'template', leftExpressionRange.start, capabilitiesPresets.all]); formatCodes.push(...createFormatCode(leftExpressionText, leftExpressionRange.start, formatBrackets.normal)); } - codes.push(`] of (await import('./__VLS_types.d.ts')).getVForSourceType`); + codes.push(`] of (await import('${sharedTypesImport}')).getVForSourceType`); if (source.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) { codes.push( ...createInterpolationCode( @@ -559,7 +560,7 @@ export function generate( } codes.push( - `const ${var_functionalComponent} = (await import('./__VLS_types.d.ts')).asFunctionalComponent(`, + `const ${var_functionalComponent} = (await import('${sharedTypesImport}')).asFunctionalComponent(`, `${var_originalComponent}, `, `new ${var_originalComponent}({`, ...createPropsCode(node, props, 'slots'), @@ -605,12 +606,12 @@ export function generate( tagOffsets.length ? ['', 'template', tagOffsets[0] + tag.length, capabilitiesPresets.diagnosticOnly] : dynamicTagExp ? ['', 'template', startTagOffset + tag.length, capabilitiesPresets.diagnosticOnly] : '', - `, ...(await import('./__VLS_types.d.ts')).functionalComponentArgsRest(${var_functionalComponent}));\n`, + `, ...(await import('${sharedTypesImport}')).functionalComponentArgsRest(${var_functionalComponent}));\n`, ); if (tag !== 'template' && tag !== 'slot') { componentCtxVar = `__VLS_${elementIndex++}`; - codes.push(`const ${componentCtxVar} = (await import('./__VLS_types.d.ts')).pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance})!;\n`); + codes.push(`const ${componentCtxVar} = (await import('${sharedTypesImport}')).pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance})!;\n`); parentEl = node; } @@ -649,7 +650,7 @@ export function generate( if (vScope?.type === CompilerDOM.NodeTypes.DIRECTIVE && vScope.exp) { const scopeVar = `__VLS_${elementIndex++}`; - const condition = `(await import('./__VLS_types.d.ts')).withScope(__VLS_ctx, ${scopeVar})`; + const condition = `(await import('${sharedTypesImport}')).withScope(__VLS_ctx, ${scopeVar})`; codes.push(`const ${scopeVar} = `); codes.push([ @@ -709,7 +710,7 @@ export function generate( slotDir.exp.loc.start.offset, capabilitiesPresets.all, ], - `] = (await import('./__VLS_types.d.ts')).getSlotParams(`, + `] = (await import('${sharedTypesImport}')).getSlotParams(`, ); } else { @@ -721,7 +722,7 @@ export function generate( slotDir.exp.loc.start.offset, capabilitiesPresets.all, ], - ` = (await import('./__VLS_types.d.ts')).getSlotParam(`, + ` = (await import('${sharedTypesImport}')).getSlotParam(`, ); } } @@ -794,7 +795,7 @@ export function generate( const eventVar = `__VLS_${elementIndex++}`; codes.push( `let ${eventVar} = { '${prop.arg.loc.source}': `, - `(await import('./__VLS_types.d.ts')).pickEvent(${componentCtxVar}.emit!, '${prop.arg.loc.source}' as const, (await import('./__VLS_types.d.ts')).componentProps(${componentVar}, ${componentInstanceVar})`, + `(await import('${sharedTypesImport}')).pickEvent(${componentCtxVar}.emit!, '${prop.arg.loc.source}' as const, (await import('${sharedTypesImport}')).componentProps(${componentVar}, ${componentInstanceVar})`, ...createPropertyAccessCode([ camelize('on-' + prop.arg.loc.source), // onClickOutside 'template', @@ -1357,7 +1358,7 @@ export function generate( prop.loc.start.offset, capabilitiesPresets.diagnosticOnly, ], - `(await import('./__VLS_types.d.ts')).directiveFunction(__VLS_ctx.`, + `(await import('${sharedTypesImport}')).directiveFunction(__VLS_ctx.`, [ camelize('v-' + prop.name), 'template', diff --git a/packages/vue-language-core/src/index.ts b/packages/vue-language-core/src/index.ts index 4f00b0666..c21311a42 100644 --- a/packages/vue-language-core/src/index.ts +++ b/packages/vue-language-core/src/index.ts @@ -1,13 +1,14 @@ export * from './generators/template'; export * from './languageModule'; -export * as scriptRanges from './parsers/scriptRanges'; export * from './parsers/scriptSetupRanges'; export * from './plugins'; export * from './sourceFile'; export * from './types'; -export * as localTypes from './utils/localTypes'; export * from './utils/ts'; export * from './utils/parseSfc'; +export * as scriptRanges from './parsers/scriptRanges'; +export * as sharedTypes from './utils/directorySharedTypes'; + export * from '@volar/language-core'; -export * from '@volar/source-map'; \ No newline at end of file +export * from '@volar/source-map'; diff --git a/packages/vue-language-core/src/languageModule.ts b/packages/vue-language-core/src/languageModule.ts index 1dbaab9ac..6627feb8d 100644 --- a/packages/vue-language-core/src/languageModule.ts +++ b/packages/vue-language-core/src/languageModule.ts @@ -3,7 +3,7 @@ import { posix as path } from 'path'; import { getDefaultVueLanguagePlugins } from './plugins'; import { VueFile } from './sourceFile'; import { VueCompilerOptions } from './types'; -import * as localTypes from './utils/localTypes'; +import * as sharedTypes from './utils/directorySharedTypes'; import type * as ts from 'typescript/lib/tsserverlibrary'; export function createLanguageModules( @@ -19,7 +19,7 @@ export function createLanguageModules( compilerOptions, vueCompilerOptions, ); - const sharedTypesSnapshot = ts.ScriptSnapshot.fromString(localTypes.getTypesCode(vueCompilerOptions.target, vueCompilerOptions)); + const sharedTypesSnapshot = ts.ScriptSnapshot.fromString(sharedTypes.getTypesCode(vueCompilerOptions.target, vueCompilerOptions)); const languageModule: embedded.LanguageModule = { createFile(fileName, snapshot, languageId) { if ( @@ -39,7 +39,7 @@ export function createLanguageModules( return { fileExists(fileName) { const basename = path.basename(fileName); - if (basename === localTypes.typesFileName) { + if (basename === sharedTypes.baseName) { return true; } return host.fileExists(fileName); @@ -53,14 +53,14 @@ export function createLanguageModules( }, getScriptVersion(fileName) { const basename = path.basename(fileName); - if (basename === localTypes.typesFileName) { + if (basename === sharedTypes.baseName) { return ''; } return host.getScriptVersion(fileName); }, getScriptSnapshot(fileName) { const basename = path.basename(fileName); - if (basename === localTypes.typesFileName) { + if (basename === sharedTypes.baseName) { return sharedTypesSnapshot; } return host.getScriptSnapshot(fileName); @@ -77,7 +77,7 @@ export function createLanguageModules( function getSharedTypesFiles(fileNames: string[]) { const moduleFiles = fileNames.filter(fileName => vueCompilerOptions.extensions.some(ext => fileName.endsWith(ext))); const moduleFileDirs = [...new Set(moduleFiles.map(path.dirname))]; - return moduleFileDirs.map(dir => path.join(dir, localTypes.typesFileName)); + return moduleFileDirs.map(dir => path.join(dir, sharedTypes.baseName)); } } diff --git a/packages/vue-language-core/src/plugins/vue-tsx.ts b/packages/vue-language-core/src/plugins/vue-tsx.ts index 6c4d5ff97..35a85cfab 100644 --- a/packages/vue-language-core/src/plugins/vue-tsx.ts +++ b/packages/vue-language-core/src/plugins/vue-tsx.ts @@ -8,11 +8,13 @@ import { FileCapabilities, FileKind } from '@volar/language-core'; import { TextRange } from '../types'; import { parseCssClassNames } from '../utils/parseCssClassNames'; import { parseCssVars } from '../utils/parseCssVars'; +import * as sharedTypes from '../utils/directorySharedTypes'; const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOptions }) => { const ts = modules.typescript; const instances = new WeakMap>(); + const sharedTypesImport = sharedTypes.getImportName(compilerOptions); return { @@ -138,6 +140,7 @@ const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOption _sfc.template?.lang ?? 'html', _sfc.templateAst, hasScriptSetupSlots.value, + sharedTypesImport, Object.values(cssScopedClasses.value).map(style => style.classNames).flat(), ); }); @@ -157,6 +160,7 @@ const plugin: VueLanguagePlugin = ({ modules, vueCompilerOptions, compilerOption htmlGen.value, compilerOptions, vueCompilerOptions, + sharedTypesImport, ); }); diff --git a/packages/vue-language-core/src/utils/localTypes.ts b/packages/vue-language-core/src/utils/directorySharedTypes.ts similarity index 95% rename from packages/vue-language-core/src/utils/localTypes.ts rename to packages/vue-language-core/src/utils/directorySharedTypes.ts index a622113a4..00a04226f 100644 --- a/packages/vue-language-core/src/utils/localTypes.ts +++ b/packages/vue-language-core/src/utils/directorySharedTypes.ts @@ -1,8 +1,16 @@ import { VueCompilerOptions } from '../types'; import { getSlotsPropertyName } from './shared'; import { getVueLibraryName } from './shared'; +import type * as ts from 'typescript/lib/tsserverlibrary'; -export const typesFileName = '__VLS_types.d.ts'; +export const baseName = '__VLS_types.d.ts'; + +export function getImportName(compilerOptions: ts.CompilerOptions) { + if (!compilerOptions.module || compilerOptions.module === 1) { + return './__VLS_types'; + } + return './__VLS_types.js'; +}; export function getTypesCode( vueVersion: number, diff --git a/packages/vue-language-service/src/helpers.ts b/packages/vue-language-service/src/helpers.ts index aa1f8802b..cb218e313 100644 --- a/packages/vue-language-service/src/helpers.ts +++ b/packages/vue-language-service/src/helpers.ts @@ -2,7 +2,7 @@ import * as vue from '@volar/vue-language-core'; import * as embedded from '@volar/language-core'; import * as CompilerDOM from '@vue/compiler-dom'; import { computed, ComputedRef } from '@vue/reactivity'; -import { typesFileName } from '@volar/vue-language-core/out/utils/localTypes'; +import { sharedTypes } from '@volar/vue-language-core'; import { camelize, capitalize } from '@vue/shared'; import type * as ts from 'typescript/lib/tsserverlibrary'; @@ -167,7 +167,7 @@ export function checkNativeTags( fileName: string, ) { - const sharedTypesFileName = fileName.substring(0, fileName.lastIndexOf('/')) + '/' + typesFileName; + const sharedTypesFileName = fileName.substring(0, fileName.lastIndexOf('/')) + '/' + sharedTypes.baseName; const result = new Set(); let tsSourceFile: ts.SourceFile | undefined; @@ -198,7 +198,7 @@ export function getElementAttrs( tagName: string, ) { - const sharedTypesFileName = fileName.substring(0, fileName.lastIndexOf('/')) + '/' + typesFileName; + const sharedTypesFileName = fileName.substring(0, fileName.lastIndexOf('/')) + '/' + sharedTypes.baseName; let tsSourceFile: ts.SourceFile | undefined;