Skip to content

Commit

Permalink
feat: vueCompilerOptions.lib
Browse files Browse the repository at this point in the history
close #2722
  • Loading branch information
johnsoncodehk committed Apr 27, 2023
1 parent 068dfd7 commit b8ae905
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- feat: support for specify vue library name by `vueCompilerOptions.lib` option ([#2730](https://github.com/johnsoncodehk/volar/issues/2730))
- fix: avoid `<component :is>` type checking with string literal assignment ([#2725](https://github.com/johnsoncodehk/volar/issues/2725))
- fix: `<slot>` 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))
Expand Down
4 changes: 4 additions & 0 deletions packages/vue-language-core/schemas/vue-tsconfig.schema.json
Expand Up @@ -19,6 +19,10 @@
"default": [ ".vue" ],
"markdownDescription": "Valid file extensions that should be considered as regular Vue SFC, please note that you should not use this option separately for additional file extensions IDE support, see https://github.com/johnsoncodehk/volar/tree/master/packages/vscode-vue/README.md#custom-file-extensions."
},
"lib": {
"default": "",
"markdownDescription": "Specify module name for import regular types. (If empty, will use `@vue/runtime-dom` for target < 2.7, `vue` for target >= 2.7)"
},
"jsxSlots": {
"type": "boolean",
"default": false,
Expand Down
39 changes: 19 additions & 20 deletions packages/vue-language-core/src/generators/script.ts
Expand Up @@ -11,7 +11,7 @@ import type { ScriptSetupRanges } from '../parsers/scriptSetupRanges';
import { collectCssVars, collectStyleCssClasses } from '../plugins/vue-tsx';
import { Sfc } from '../types';
import type { VueCompilerOptions } from '../types';
import { getSlotsPropertyName, getVueLibraryName } from '../utils/shared';
import { getSlotsPropertyName } from '../utils/shared';
import { walkInterpolationFragment } from '../utils/transform';
import * as sharedTypes from '../utils/directorySharedTypes';
import * as muggle from 'muggle-string';
Expand Down Expand Up @@ -72,7 +72,6 @@ export function generate(
//#endregion

const bypassDefineComponent = lang === 'js' || lang === 'jsx';
const vueLibName = getVueLibraryName(vueCompilerOptions.target);
const usedHelperTypes = {
DefinePropsToOptions: false,
mergePropDefaults: false,
Expand Down Expand Up @@ -116,11 +115,11 @@ export function generate(
let usedPrettify = false;
if (usedHelperTypes.DefinePropsToOptions) {
if (compilerOptions.exactOptionalPropertyTypes) {
codes.push(`type __VLS_TypePropsToRuntimeProps<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? { type: import('${vueLibName}').PropType<T[K]> } : { type: import('${vueLibName}').PropType<T[K]>, required: true } };\n`);
codes.push(`type __VLS_TypePropsToRuntimeProps<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? { type: import('${vueCompilerOptions.lib}').PropType<T[K]> } : { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true } };\n`);
}
else {
codes.push(`type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;\n`);
codes.push(`type __VLS_TypePropsToRuntimeProps<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? { type: import('${vueLibName}').PropType<__VLS_NonUndefinedable<T[K]>> } : { type: import('${vueLibName}').PropType<T[K]>, required: true } };\n`);
codes.push(`type __VLS_TypePropsToRuntimeProps<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable<T[K]>> } : { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true } };\n`);
}
}
if (usedHelperTypes.mergePropDefaults) {
Expand Down Expand Up @@ -317,9 +316,9 @@ export function generate(
codes.push('(\n');
codes.push(
`__VLS_props: typeof __VLS_setup['props']`,
`& import('${vueLibName}').VNodeProps`,
`& import('${vueLibName}').AllowedComponentProps`,
`& import('${vueLibName}').ComponentCustomProps,\n`,
`& import('${vueCompilerOptions.lib}').VNodeProps`,
`& import('${vueCompilerOptions.lib}').AllowedComponentProps`,
`& import('${vueCompilerOptions.lib}').ComponentCustomProps,\n`,
);
codes.push(`__VLS_ctx?: Pick<typeof __VLS_setup, 'attrs' | 'emit' | 'slots'>,\n`);
codes.push('__VLS_setup = (() => {\n');
Expand Down Expand Up @@ -437,7 +436,7 @@ export function generate(
codes.push('emit: typeof __VLS_emit');
codes.push('};\n');
codes.push('})(),\n');
codes.push(`) => ({} as import('${vueLibName}').VNode & { __ctx?: typeof __VLS_setup }))`);
codes.push(`) => ({} as import('${vueCompilerOptions.lib}').VNode & { __ctx?: typeof __VLS_setup }))`);
}
else if (!sfc.script) {
// no script block, generate script setup code at root
Expand Down Expand Up @@ -484,20 +483,20 @@ export function generate(
const definePropProposalB = sfc.scriptSetup.content.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition') || vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';

if (vueCompilerOptions.target >= 3.3) {
codes.push(`const { defineProps, defineEmits, defineExpose, defineOptions, defineSlots, defineModel, withDefaults } = await import('${vueLibName}');\n`);
codes.push(`const { defineProps, defineEmits, defineExpose, defineOptions, defineSlots, defineModel, withDefaults } = await import('${vueCompilerOptions.lib}');\n`);
}
if (definePropProposalA) {
codes.push(`
declare function defineProp<T>(name: string, options: { required: true } & Record<string, unknown>): import('${vueLibName}').ComputedRef<T>;
declare function defineProp<T>(name: string, options: { default: any } & Record<string, unknown>): import('${vueLibName}').ComputedRef<T>;
declare function defineProp<T>(name?: string, options?: any): import('${vueLibName}').ComputedRef<T | undefined>;
declare function defineProp<T>(name: string, options: { required: true } & Record<string, unknown>): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(name: string, options: { default: any } & Record<string, unknown>): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(name?: string, options?: any): import('${vueCompilerOptions.lib}').ComputedRef<T | undefined>;
`.trim() + '\n');
}
if (definePropProposalB) {
codes.push(`
declare function defineProp<T>(value: T | (() => T), required?: boolean, rest?: any): import('${vueLibName}').ComputedRef<T>;
declare function defineProp<T>(value: T | (() => T) | undefined, required: true, rest?: any): import('${vueLibName}').ComputedRef<T>;
declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?: any): import('${vueLibName}').ComputedRef<T | undefined>;
declare function defineProp<T>(value: T | (() => T), required?: boolean, rest?: any): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(value: T | (() => T) | undefined, required: true, rest?: any): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?: any): import('${vueCompilerOptions.lib}').ComputedRef<T | undefined>;
`.trim() + '\n');
}

Expand All @@ -519,7 +518,7 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
codes.push(`{\n`);
}
else {
codes.push(`const __VLS_publicComponent = (await import('${vueLibName}')).defineComponent({\n`);
codes.push(`const __VLS_publicComponent = (await import('${vueCompilerOptions.lib}')).defineComponent({\n`);
}

if (scriptSetupRanges.defineProp.length) {
Expand Down Expand Up @@ -552,10 +551,10 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
}

if (defineProp.required) {
codes.push(`{ required: true, type: import('${vueLibName}').PropType<${type}> },\n`);
codes.push(`{ required: true, type: import('${vueCompilerOptions.lib}').PropType<${type}> },\n`);
}
else {
codes.push(`import('${vueLibName}').PropType<${type}>,\n`);
codes.push(`import('${vueCompilerOptions.lib}').PropType<${type}>,\n`);
}
}
codes.push(`},\n`);
Expand Down Expand Up @@ -714,7 +713,7 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:

if (sfc.scriptSetup && scriptSetupRanges) {

codes.push(`const __VLS_internalComponent = (await import('${vueLibName}')).defineComponent({\n`);
codes.push(`const __VLS_internalComponent = (await import('${vueCompilerOptions.lib}')).defineComponent({\n`);
codes.push(`setup() {\n`);
codes.push(`return {\n`);
// fill ctx from props
Expand Down Expand Up @@ -776,7 +775,7 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
codes.push(`let __VLS_internalComponent!: typeof import('./${path.basename(fileName)}')['default'];\n`);
}
else {
codes.push(`const __VLS_internalComponent = (await import('${vueLibName}')).defineComponent({});\n`);
codes.push(`const __VLS_internalComponent = (await import('${vueCompilerOptions.lib}')).defineComponent({});\n`);
}
}
function generateExportOptions() {
Expand Down
2 changes: 1 addition & 1 deletion packages/vue-language-core/src/languageModule.ts
Expand Up @@ -19,7 +19,7 @@ export function createLanguageModules(
compilerOptions,
vueCompilerOptions,
);
const sharedTypesSnapshot = ts.ScriptSnapshot.fromString(sharedTypes.getTypesCode(vueCompilerOptions.target, vueCompilerOptions));
const sharedTypesSnapshot = ts.ScriptSnapshot.fromString(sharedTypes.getTypesCode(vueCompilerOptions));
const languageModule: embedded.LanguageModule = {
createFile(fileName, snapshot, languageId) {
if (
Expand Down
1 change: 1 addition & 0 deletions packages/vue-language-core/src/types.ts
Expand Up @@ -18,6 +18,7 @@ export type RawVueCompilerOptions = Partial<Omit<VueCompilerOptions, 'target' |

export interface VueCompilerOptions {
target: number;
lib: string;
extensions: string[];
jsxSlots: boolean;
strictTemplates: boolean;
Expand Down
11 changes: 3 additions & 8 deletions packages/vue-language-core/src/utils/directorySharedTypes.ts
@@ -1,6 +1,5 @@
import { VueCompilerOptions } from '../types';
import { getSlotsPropertyName } from './shared';
import { getVueLibraryName } from './shared';
import type * as ts from 'typescript/lib/tsserverlibrary';

export const baseName = '__VLS_types.d.ts';
Expand All @@ -12,18 +11,14 @@ export function getImportName(compilerOptions: ts.CompilerOptions) {
return './__VLS_types.js';
};

export function getTypesCode(
vueVersion: number,
vueCompilerOptions: VueCompilerOptions,
) {
const libName = getVueLibraryName(vueVersion);
export function getTypesCode(vueCompilerOptions: VueCompilerOptions) {
return `
// @ts-nocheck
import type {
ObjectDirective,
FunctionDirective,
VNode,
} from '${libName}';
} from '${vueCompilerOptions.lib}';
export type IntrinsicElements = PickNotAny<import('vue/jsx-runtime').JSX.IntrinsicElements, PickNotAny<JSX.IntrinsicElements, Record<string, any>>>;
export type Element = PickNotAny<import('vue/jsx-runtime').JSX.Element, JSX.Element>;
Expand All @@ -47,7 +42,7 @@ export type GlobalComponents =
& PickNotAny<import('@vue/runtime-core').GlobalComponents, {}>
// @ts-ignore
& PickNotAny<import('@vue/runtime-dom').GlobalComponents, {}>
& Pick<typeof import('${libName}'),
& Pick<typeof import('${vueCompilerOptions.lib}'),
// @ts-ignore
'Transition'
| 'TransitionGroup'
Expand Down
4 changes: 0 additions & 4 deletions packages/vue-language-core/src/utils/shared.ts
@@ -1,7 +1,3 @@
export function getSlotsPropertyName(vueVersion: number) {
return vueVersion < 3 ? '$scopedSlots' : '$slots';
}

export function getVueLibraryName(vueVersion: number) {
return vueVersion < 2.7 ? '@vue/runtime-dom' : 'vue';
}
1 change: 1 addition & 0 deletions packages/vue-language-core/src/utils/ts.ts
Expand Up @@ -176,6 +176,7 @@ export function resolveVueCompilerOptions(vueOptions: Partial<VueCompilerOptions
...vueOptions,
target,
extensions: vueOptions.extensions ?? ['.vue'],
lib: vueOptions.lib || (target < 2.7 ? '@vue/runtime-dom' : 'vue'),
jsxSlots: vueOptions.jsxSlots ?? false,
strictTemplates: vueOptions.strictTemplates ?? false,
skipTemplateCodegen: vueOptions.skipTemplateCodegen ?? false,
Expand Down

0 comments on commit b8ae905

Please sign in to comment.