@vue/language-core
Advanced tools
Comparing version 2.0.29 to 2.1.0
@@ -0,1 +1,2 @@ | ||
export * from './lib/codegen/globalTypes'; | ||
export * from './lib/codegen/template'; | ||
@@ -5,10 +6,10 @@ export * from './lib/languagePlugin'; | ||
export * from './lib/plugins'; | ||
export * from './lib/virtualFile/vueFile'; | ||
export * from './lib/types'; | ||
export * from './lib/utils/parseSfc'; | ||
export * from './lib/utils/ts'; | ||
export * from './lib/utils/parseSfc'; | ||
export * from './lib/virtualFile/vueFile'; | ||
export * as scriptRanges from './lib/parsers/scriptRanges'; | ||
export { tsCodegen } from './lib/plugins/vue-tsx'; | ||
export * from './lib/utils/shared'; | ||
export { tsCodegen } from './lib/plugins/vue-tsx'; | ||
export * from '@volar/language-core'; | ||
export type * as CompilerDOM from '@vue/compiler-dom'; |
@@ -18,2 +18,3 @@ "use strict"; | ||
exports.tsCodegen = exports.scriptRanges = void 0; | ||
__exportStar(require("./lib/codegen/globalTypes"), exports); | ||
__exportStar(require("./lib/codegen/template"), exports); | ||
@@ -23,11 +24,11 @@ __exportStar(require("./lib/languagePlugin"), exports); | ||
__exportStar(require("./lib/plugins"), exports); | ||
__exportStar(require("./lib/virtualFile/vueFile"), exports); | ||
__exportStar(require("./lib/types"), exports); | ||
__exportStar(require("./lib/utils/parseSfc"), exports); | ||
__exportStar(require("./lib/utils/ts"), exports); | ||
__exportStar(require("./lib/utils/parseSfc"), exports); | ||
__exportStar(require("./lib/virtualFile/vueFile"), exports); | ||
exports.scriptRanges = require("./lib/parsers/scriptRanges"); | ||
__exportStar(require("./lib/utils/shared"), exports); | ||
var vue_tsx_1 = require("./lib/plugins/vue-tsx"); | ||
Object.defineProperty(exports, "tsCodegen", { enumerable: true, get: function () { return vue_tsx_1.tsCodegen; } }); | ||
__exportStar(require("./lib/utils/shared"), exports); | ||
__exportStar(require("@volar/language-core"), exports); | ||
//# sourceMappingURL=index.js.map |
@@ -9,4 +9,5 @@ import type * as ts from 'typescript'; | ||
export declare function wrapWith(startOffset: number, endOffset: number, features: VueCodeInformation, ...wrapCodes: Code[]): Generator<Code>; | ||
export declare function collectVars(ts: typeof import('typescript'), node: ts.Node, ast: ts.SourceFile, result: string[]): void; | ||
export declare function collectVars(ts: typeof import('typescript'), node: ts.Node, ast: ts.SourceFile, results?: string[], includesRest?: boolean): string[]; | ||
export declare function collectIdentifiers(ts: typeof import('typescript'), node: ts.Node, results?: ts.Identifier[], includesRest?: boolean): ts.Identifier[]; | ||
export declare function createTsAst(ts: typeof import('typescript'), astHolder: any, text: string): ts.SourceFile; | ||
export declare function generateSfcBlockSection(block: SfcBlock, start: number, end: number, features: VueCodeInformation): Code; |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.collectVars = collectVars; | ||
exports.collectIdentifiers = collectIdentifiers; | ||
exports.createTsAst = createTsAst; | ||
@@ -36,9 +37,18 @@ exports.generateSfcBlockSection = generateSfcBlockSection; | ||
} | ||
function collectVars(ts, node, ast, result) { | ||
function collectVars(ts, node, ast, results = [], includesRest = true) { | ||
const identifiers = collectIdentifiers(ts, node, [], includesRest); | ||
for (const id of identifiers) { | ||
results.push((0, scriptSetupRanges_1.getNodeText)(ts, id, ast)); | ||
} | ||
return results; | ||
} | ||
function collectIdentifiers(ts, node, results = [], includesRest = true) { | ||
if (ts.isIdentifier(node)) { | ||
result.push((0, scriptSetupRanges_1.getNodeText)(ts, node, ast)); | ||
results.push(node); | ||
} | ||
else if (ts.isObjectBindingPattern(node)) { | ||
for (const el of node.elements) { | ||
collectVars(ts, el.name, ast, result); | ||
if (includesRest || !el.dotDotDotToken) { | ||
collectIdentifiers(ts, el.name, results, includesRest); | ||
} | ||
} | ||
@@ -49,3 +59,3 @@ } | ||
if (ts.isBindingElement(el)) { | ||
collectVars(ts, el.name, ast, result); | ||
collectIdentifiers(ts, el.name, results, includesRest); | ||
} | ||
@@ -55,4 +65,5 @@ } | ||
else { | ||
ts.forEachChild(node, node => collectVars(ts, node, ast, result)); | ||
ts.forEachChild(node, node => collectIdentifiers(ts, node, results, includesRest)); | ||
} | ||
return results; | ||
} | ||
@@ -59,0 +70,0 @@ function createTsAst(ts, astHolder, text) { |
@@ -1,2 +0,1 @@ | ||
import type { ScriptRanges } from '../../parsers/scriptRanges'; | ||
import type { ScriptSetupRanges } from '../../parsers/scriptSetupRanges'; | ||
@@ -8,5 +7,3 @@ import type { Code, Sfc } from '../../types'; | ||
export declare function generateComponentSetupReturns(scriptSetupRanges: ScriptSetupRanges): Generator<Code>; | ||
export declare function generateScriptOptions(script: NonNullable<Sfc['script']>, scriptRanges: ScriptRanges): Generator<Code>; | ||
export declare function generateScriptSetupOptions(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges): Generator<Code>; | ||
export declare function generatePropsOption(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges): Generator<Code, void, unknown>; | ||
export declare function generateEmitsOption(options: ScriptCodegenOptions, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges): Generator<Code>; | ||
export declare function generatePropsOption(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, scriptSetup: NonNullable<Sfc['scriptSetup']>, scriptSetupRanges: ScriptSetupRanges, hasEmitsOption: boolean, inheritAttrs: boolean): Generator<Code>; |
@@ -5,6 +5,4 @@ "use strict"; | ||
exports.generateComponentSetupReturns = generateComponentSetupReturns; | ||
exports.generateScriptOptions = generateScriptOptions; | ||
exports.generateScriptSetupOptions = generateScriptSetupOptions; | ||
exports.generateEmitsOption = generateEmitsOption; | ||
exports.generatePropsOption = generatePropsOption; | ||
exports.generateEmitsOption = generateEmitsOption; | ||
const common_1 = require("../common"); | ||
@@ -32,7 +30,15 @@ const index_1 = require("./index"); | ||
if (!ctx.bypassDefineComponent) { | ||
yield* generateScriptSetupOptions(options, ctx, scriptSetup, scriptSetupRanges); | ||
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 (0, common_1.generateSfcBlockSection)(options.sfc.script, args.start + 1, args.end - 1, index_1.codeFeatures.all); | ||
} | ||
if (options.vueCompilerOptions.target >= 3.5 && scriptSetupRanges.templateRefs.length) { | ||
yield `__typeRefs: {} as __VLS_Refs,${common_1.newLine}`; | ||
} | ||
yield `})`; | ||
@@ -52,48 +58,46 @@ } | ||
} | ||
function* generateScriptOptions(script, scriptRanges) { | ||
if (scriptRanges.exportDefault?.args) { | ||
yield (0, common_1.generateSfcBlockSection)(script, scriptRanges.exportDefault.args.start + 1, scriptRanges.exportDefault.args.end - 1, index_1.codeFeatures.all); | ||
function* generateEmitsOption(options, scriptSetup, scriptSetupRanges) { | ||
const codes = []; | ||
if (scriptSetupRanges.defineProp.some(p => p.isModel)) { | ||
codes.push({ | ||
optionExp: `{} as __VLS_NormalizeEmits<__VLS_ModelEmitsType>`, | ||
typeOptionType: `__VLS_ModelEmitsType`, | ||
}); | ||
} | ||
} | ||
function* generateScriptSetupOptions(options, ctx, scriptSetup, scriptSetupRanges) { | ||
yield* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges); | ||
yield* generateEmitsOption(options, scriptSetup, scriptSetupRanges); | ||
} | ||
function* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges) { | ||
if (options.vueCompilerOptions.target >= 3.5 && ctx.generatedPropsType) { | ||
yield `__typeProps: {} as __VLS_PublicProps,${common_1.newLine}`; | ||
if (scriptSetupRanges.emits.define) { | ||
const { typeArg, hasUnionTypeArg } = scriptSetupRanges.emits.define; | ||
codes.push({ | ||
optionExp: `{} as __VLS_NormalizeEmits<typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'}>`, | ||
typeOptionType: typeArg && !hasUnionTypeArg | ||
? scriptSetup.content.slice(typeArg.start, typeArg.end) | ||
: undefined, | ||
}); | ||
} | ||
if (options.vueCompilerOptions.target < 3.5 || !ctx.generatedPropsType || scriptSetupRanges.props.withDefaults) { | ||
const codegens = []; | ||
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 (options.vueCompilerOptions.target >= 3.5 && codes.every(code => code.typeOptionType)) { | ||
if (codes.length === 1) { | ||
yield `__typeEmits: {} as `; | ||
yield codes[0].typeOptionType; | ||
yield `,${common_1.newLine}`; | ||
} | ||
if (scriptSetupRanges.props.define?.arg) { | ||
const { arg } = scriptSetupRanges.props.define; | ||
codegens.push(function* () { | ||
yield (0, common_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, index_1.codeFeatures.navigation); | ||
}); | ||
} | ||
if (codegens.length === 1) { | ||
yield `props: `; | ||
for (const generate of codegens) { | ||
yield* generate(); | ||
else if (codes.length >= 2) { | ||
yield `__typeEmits: {} as `; | ||
yield codes[0].typeOptionType; | ||
for (let i = 1; i < codes.length; i++) { | ||
yield ` & `; | ||
yield codes[i].typeOptionType; | ||
} | ||
yield `,${common_1.newLine}`; | ||
} | ||
else if (codegens.length >= 2) { | ||
yield `props: {${common_1.newLine}`; | ||
for (const generate of codegens) { | ||
} | ||
else if (codes.every(code => code.optionExp)) { | ||
if (codes.length === 1) { | ||
yield `emits: `; | ||
yield codes[0].optionExp; | ||
yield `,${common_1.newLine}`; | ||
} | ||
else if (codes.length >= 2) { | ||
yield `emits: {${common_1.newLine}`; | ||
for (const code of codes) { | ||
yield `...`; | ||
yield* generate(); | ||
yield code.optionExp; | ||
yield `,${common_1.newLine}`; | ||
@@ -105,24 +109,69 @@ } | ||
} | ||
function* generateEmitsOption(options, scriptSetup, scriptSetupRanges) { | ||
if (!scriptSetupRanges.emits.define && !scriptSetupRanges.defineProp.some(p => p.isModel)) { | ||
return; | ||
function* generatePropsOption(options, ctx, scriptSetup, scriptSetupRanges, hasEmitsOption, inheritAttrs) { | ||
const optionExpCodes = []; | ||
const typeOptionExpCodes = []; | ||
if (ctx.generatedPropsType) { | ||
optionExpCodes.push([ | ||
`{} as `, | ||
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`); | ||
} | ||
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.props.define?.arg) { | ||
const { arg } = scriptSetupRanges.props.define; | ||
optionExpCodes.push((0, common_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, index_1.codeFeatures.navigation)); | ||
} | ||
if (inheritAttrs && options.templateCodegen?.inheritedAttrVars.size) { | ||
let attrsType = `typeof __VLS_templateResult['attrs']`; | ||
if (hasEmitsOption) { | ||
attrsType = `Omit<${attrsType}, \`on\${string}\`>`; | ||
} | ||
yield `>),${common_1.newLine}`; | ||
const propsType = `__VLS_PickNotAny<${ctx.localTypes.OmitIndexSignature}<${attrsType}>, {}>`; | ||
const optionType = `${ctx.localTypes.TypePropsToOption}<${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}`); | ||
} | ||
else { | ||
yield `__typeEmits: {} as __VLS_ModelEmitsType`; | ||
const typeArg = scriptSetupRanges.emits.define?.typeArg; | ||
if (typeArg) { | ||
yield ` & `; | ||
yield scriptSetup.content.slice(typeArg.start, typeArg.end); | ||
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 `,${common_1.newLine}`; | ||
} | ||
yield `,${common_1.newLine}`; | ||
else if (typeOptionExpCodes.length >= 2) { | ||
yield `__typeProps: {${common_1.newLine}`; | ||
for (const code of typeOptionExpCodes) { | ||
yield `...`; | ||
yield code; | ||
yield `,${common_1.newLine}`; | ||
} | ||
yield `},${common_1.newLine}`; | ||
} | ||
} | ||
if (useOption) { | ||
if (optionExpCodes.length === 1) { | ||
yield `props: `; | ||
yield optionExpCodes[0]; | ||
yield `,${common_1.newLine}`; | ||
} | ||
else if (optionExpCodes.length >= 2) { | ||
yield `props: {${common_1.newLine}`; | ||
for (const code of optionExpCodes) { | ||
yield `...`; | ||
yield code; | ||
yield `,${common_1.newLine}`; | ||
} | ||
yield `},${common_1.newLine}`; | ||
} | ||
} | ||
} | ||
//# sourceMappingURL=component.js.map |
@@ -0,3 +1,4 @@ | ||
import { InlayHintInfo } from '../types'; | ||
import type { ScriptCodegenOptions } from './index'; | ||
interface HelperType { | ||
export interface HelperType { | ||
name: string; | ||
@@ -15,12 +16,15 @@ used?: boolean; | ||
bindingNames: Set<string>; | ||
helperTypes: { | ||
OmitKeepDiscriminatedUnion: HelperType; | ||
WithDefaults: HelperType; | ||
Prettify: HelperType; | ||
WithTemplateSlots: HelperType; | ||
PropsChildren: HelperType; | ||
TypePropsToOption: HelperType; | ||
localTypes: { | ||
generate: (names: string[]) => Generator<string, void, unknown>; | ||
getUsedNames(): Set<string>; | ||
readonly PrettifyLocal: string; | ||
readonly OmitKeepDiscriminatedUnion: string; | ||
readonly WithDefaults: string; | ||
readonly WithTemplateSlots: string; | ||
readonly PropsChildren: string; | ||
readonly TypePropsToOption: string; | ||
readonly OmitIndexSignature: string; | ||
readonly PickRefsExpose: string; | ||
}; | ||
generateHelperTypes: () => Generator<string, void, unknown>; | ||
inlayHints: InlayHintInfo[]; | ||
}; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createScriptCodegenContext = createScriptCodegenContext; | ||
const shared_1 = require("../../utils/shared"); | ||
const common_1 = require("../common"); | ||
const localTypes_1 = require("../localTypes"); | ||
function createScriptCodegenContext(options) { | ||
const helperTypes = { | ||
OmitKeepDiscriminatedUnion: { | ||
get name() { | ||
this.used = true; | ||
return `__VLS_OmitKeepDiscriminatedUnion`; | ||
}, | ||
get code() { | ||
return `type __VLS_OmitKeepDiscriminatedUnion<T, K extends keyof any> = T extends any | ||
? Pick<T, Exclude<keyof T, K>> | ||
: never;`; | ||
}, | ||
}, | ||
WithDefaults: { | ||
get name() { | ||
this.used = true; | ||
return `__VLS_WithDefaults`; | ||
}, | ||
get code() { | ||
return `type __VLS_WithDefaults<P, D> = { | ||
[K in keyof Pick<P, keyof P>]: K extends keyof D | ||
? ${helperTypes.Prettify.name}<P[K] & { default: D[K]}> | ||
: P[K] | ||
};`; | ||
}, | ||
}, | ||
Prettify: { | ||
get name() { | ||
this.used = true; | ||
return `__VLS_Prettify`; | ||
}, | ||
get code() { | ||
return `type __VLS_Prettify<T> = { [K in keyof T]: T[K]; } & {};`; | ||
}, | ||
}, | ||
WithTemplateSlots: { | ||
get name() { | ||
this.used = true; | ||
return `__VLS_WithTemplateSlots`; | ||
}, | ||
get code() { | ||
return `type __VLS_WithTemplateSlots<T, S> = T & { | ||
new(): { | ||
${(0, shared_1.getSlotsPropertyName)(options.vueCompilerOptions.target)}: S; | ||
${options.vueCompilerOptions.jsxSlots ? `$props: ${helperTypes.PropsChildren.name}<S>;` : ''} | ||
} | ||
};`; | ||
}, | ||
}, | ||
PropsChildren: { | ||
get name() { | ||
this.used = true; | ||
return `__VLS_PropsChildren`; | ||
}, | ||
get code() { | ||
return `type __VLS_PropsChildren<S> = { | ||
[K in keyof ( | ||
boolean extends ( | ||
// @ts-ignore | ||
JSX.ElementChildrenAttribute extends never | ||
? true | ||
: false | ||
) | ||
? never | ||
// @ts-ignore | ||
: JSX.ElementChildrenAttribute | ||
)]?: S; | ||
};`; | ||
}, | ||
}, | ||
TypePropsToOption: { | ||
get name() { | ||
this.used = true; | ||
return `__VLS_TypePropsToOption`; | ||
}, | ||
get code() { | ||
return options.compilerOptions.exactOptionalPropertyTypes ? | ||
`type __VLS_TypePropsToOption<T> = { | ||
[K in keyof T]-?: {} extends Pick<T, K> | ||
? { type: import('${options.vueCompilerOptions.lib}').PropType<T[K]> } | ||
: { type: import('${options.vueCompilerOptions.lib}').PropType<T[K]>, required: true } | ||
};` : | ||
`type __VLS_NonUndefinedable<T> = T extends undefined ? never : T; | ||
type __VLS_TypePropsToOption<T> = { | ||
[K in keyof T]-?: {} extends Pick<T, K> | ||
? { type: import('${options.vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable<T[K]>> } | ||
: { type: import('${options.vueCompilerOptions.lib}').PropType<T[K]>, required: true } | ||
};`; | ||
}, | ||
}, | ||
}; | ||
const localTypes = (0, localTypes_1.getLocalTypesGenerator)(options.compilerOptions, options.vueCompilerOptions); | ||
const inlayHints = []; | ||
return { | ||
@@ -106,19 +17,6 @@ generatedTemplate: false, | ||
]), | ||
helperTypes, | ||
generateHelperTypes, | ||
localTypes, | ||
inlayHints, | ||
}; | ||
function* generateHelperTypes() { | ||
let shouldCheck = true; | ||
while (shouldCheck) { | ||
shouldCheck = false; | ||
for (const helperType of Object.values(helperTypes)) { | ||
if (helperType.used && !helperType.generated) { | ||
shouldCheck = true; | ||
helperType.generated = true; | ||
yield common_1.newLine + helperType.code + common_1.newLine; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
//# sourceMappingURL=context.js.map |
@@ -7,2 +7,3 @@ import type { Mapping } from '@volar/language-core'; | ||
import type { TemplateCodegenContext } from '../template/context'; | ||
import { ScriptCodegenContext } from './context'; | ||
export declare const codeFeatures: { | ||
@@ -27,6 +28,6 @@ all: VueCodeInformation; | ||
} | undefined; | ||
globalTypes: boolean; | ||
edited: boolean; | ||
getGeneratedLength: () => number; | ||
linkedCodeMappings: Mapping[]; | ||
} | ||
export declare function generateScript(options: ScriptCodegenOptions): Generator<Code>; | ||
export declare function generateScript(options: ScriptCodegenOptions): Generator<Code, ScriptCodegenContext>; |
@@ -7,3 +7,2 @@ "use strict"; | ||
const context_1 = require("./context"); | ||
const globalTypes_1 = require("./globalTypes"); | ||
const scriptSetup_1 = require("./scriptSetup"); | ||
@@ -36,3 +35,3 @@ const src_1 = require("./src"); | ||
const ctx = (0, context_1.createScriptCodegenContext)(options); | ||
yield `/* __placeholder__ */${common_1.newLine}`; | ||
yield `/// <reference types="${options.vueCompilerOptions.lib}/__globalTypes_${options.vueCompilerOptions.target}_${options.vueCompilerOptions.strictTemplates}" />${common_1.newLine}`; | ||
if (options.sfc.script?.src) { | ||
@@ -59,36 +58,24 @@ yield* (0, src_1.generateSrc)(options.sfc.script, options.sfc.script.src); | ||
else if (exportDefault && isExportRawObject && options.vueCompilerOptions.optionsWrapper.length) { | ||
ctx.inlayHints.push({ | ||
blockName: options.sfc.script.name, | ||
offset: exportDefault.expression.start, | ||
setting: 'vue.inlayHints.optionsWrapper', | ||
label: options.vueCompilerOptions.optionsWrapper.length | ||
? options.vueCompilerOptions.optionsWrapper[0] | ||
: '[Missing optionsWrapper[0]]', | ||
tooltip: [ | ||
'This is virtual code that is automatically wrapped for type support, it does not affect your runtime behavior, you can customize it via `vueCompilerOptions.optionsWrapper` option in tsconfig / jsconfig.', | ||
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.', | ||
].join('\n\n'), | ||
}, { | ||
blockName: options.sfc.script.name, | ||
offset: exportDefault.expression.end, | ||
setting: 'vue.inlayHints.optionsWrapper', | ||
label: options.vueCompilerOptions.optionsWrapper.length >= 2 | ||
? options.vueCompilerOptions.optionsWrapper[1] | ||
: '[Missing optionsWrapper[1]]', | ||
}); | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, 0, exportDefault.expression.start, exports.codeFeatures.all); | ||
yield options.vueCompilerOptions.optionsWrapper[0]; | ||
yield [ | ||
'', | ||
'script', | ||
exportDefault.expression.start, | ||
{ | ||
__hint: { | ||
setting: 'vue.inlayHints.optionsWrapper', | ||
label: options.vueCompilerOptions.optionsWrapper.length | ||
? options.vueCompilerOptions.optionsWrapper[0] | ||
: '[Missing optionsWrapper]', | ||
tooltip: [ | ||
'This is virtual code that is automatically wrapped for type support, it does not affect your runtime behavior, you can customize it via `vueCompilerOptions.optionsWrapper` option in tsconfig / jsconfig.', | ||
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.', | ||
].join('\n\n'), | ||
} | ||
}, | ||
]; | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.start, exportDefault.expression.end, exports.codeFeatures.all); | ||
yield [ | ||
'', | ||
'script', | ||
exportDefault.expression.end, | ||
{ | ||
__hint: { | ||
setting: 'vue.inlayHints.optionsWrapper', | ||
label: options.vueCompilerOptions.optionsWrapper.length === 2 | ||
? options.vueCompilerOptions.optionsWrapper[1] | ||
: '[Missing optionsWrapper]', | ||
tooltip: '', | ||
} | ||
}, | ||
]; | ||
yield options.vueCompilerOptions.optionsWrapper[1]; | ||
@@ -98,5 +85,12 @@ yield (0, common_1.generateSfcBlockSection)(options.sfc.script, exportDefault.expression.end, options.sfc.script.content.length, exports.codeFeatures.all); | ||
else if (classBlockEnd !== undefined) { | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, 0, classBlockEnd, exports.codeFeatures.all); | ||
yield* (0, template_1.generateTemplate)(options, ctx, true); | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, classBlockEnd, options.sfc.script.content.length, exports.codeFeatures.all); | ||
if (options.vueCompilerOptions.skipTemplateCodegen) { | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, exports.codeFeatures.all); | ||
} | ||
else { | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, 0, classBlockEnd, exports.codeFeatures.all); | ||
yield `__VLS_template = () => {`; | ||
yield* (0, template_1.generateTemplate)(options, ctx, true); | ||
yield `},${common_1.newLine}`; | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, classBlockEnd, options.sfc.script.content.length, exports.codeFeatures.all); | ||
} | ||
} | ||
@@ -115,26 +109,16 @@ else { | ||
// #4569 | ||
yield [ | ||
'', | ||
'scriptSetup', | ||
options.sfc.scriptSetup.content.length, | ||
exports.codeFeatures.verification, | ||
]; | ||
yield ['', 'scriptSetup', options.sfc.scriptSetup.content.length, exports.codeFeatures.verification]; | ||
} | ||
yield common_1.newLine; | ||
if (options.globalTypes) { | ||
yield (0, globalTypes_1.generateGlobalTypes)(options.vueCompilerOptions); | ||
} | ||
yield* ctx.generateHelperTypes(); | ||
yield `\ntype __VLS_IntrinsicElementsCompletion = __VLS_IntrinsicElements${common_1.endOfLine}`; | ||
if (!ctx.generatedTemplate) { | ||
yield* (0, template_1.generateTemplate)(options, ctx, false); | ||
} | ||
if (options.edited) { | ||
yield `type __VLS_IntrinsicElementsCompletion = __VLS_IntrinsicElements${common_1.endOfLine}`; | ||
} | ||
yield* ctx.localTypes.generate([...ctx.localTypes.getUsedNames()]); | ||
if (options.sfc.scriptSetup) { | ||
yield [ | ||
'', | ||
'scriptSetup', | ||
options.sfc.scriptSetup.content.length, | ||
exports.codeFeatures.verification, | ||
]; | ||
yield ['', 'scriptSetup', options.sfc.scriptSetup.content.length, exports.codeFeatures.verification]; | ||
} | ||
return ctx; | ||
} | ||
@@ -141,0 +125,0 @@ function* generateDefineProp(options, scriptSetup) { |
import type { Code } from '../../types'; | ||
import type { TemplateCodegenContext } from '../template/context'; | ||
import type { ScriptCodegenContext } from './context'; | ||
import type { ScriptCodegenOptions } from './index'; | ||
import { type ScriptCodegenOptions } from './index'; | ||
export declare function generateInternalComponent(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, templateCodegenCtx: TemplateCodegenContext): Generator<Code>; |
@@ -6,7 +6,7 @@ "use strict"; | ||
const component_1 = require("./component"); | ||
const index_1 = require("./index"); | ||
const template_1 = require("./template"); | ||
function* generateInternalComponent(options, ctx, templateCodegenCtx) { | ||
if (options.sfc.scriptSetup && options.scriptSetupRanges) { | ||
yield `let __VLS_defineComponent!: typeof import('${options.vueCompilerOptions.lib}').defineComponent${common_1.endOfLine}`; | ||
yield `const __VLS_internalComponent = __VLS_defineComponent({${common_1.newLine}`; | ||
yield `const __VLS_internalComponent = (await import('${options.vueCompilerOptions.lib}')).defineComponent({${common_1.newLine}`; | ||
yield `setup() {${common_1.newLine}`; | ||
@@ -44,7 +44,15 @@ yield `return {${common_1.newLine}`; | ||
yield `},${common_1.newLine}`; // setup() { | ||
if (options.vueCompilerOptions.target >= 3.5) { | ||
yield `__typeRefs: {} as __VLS_Refs,${common_1.newLine}`; | ||
} | ||
if (options.sfc.scriptSetup && options.scriptSetupRanges && !ctx.bypassDefineComponent) { | ||
yield* (0, component_1.generateScriptSetupOptions)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges); | ||
const emitOptionCodes = [...(0, component_1.generateEmitsOption)(options, options.sfc.scriptSetup, options.scriptSetupRanges)]; | ||
for (const code of emitOptionCodes) { | ||
yield code; | ||
} | ||
yield* (0, component_1.generatePropsOption)(options, ctx, options.sfc.scriptSetup, options.scriptSetupRanges, !!emitOptionCodes.length, false); | ||
} | ||
if (options.sfc.script && options.scriptRanges) { | ||
yield* (0, component_1.generateScriptOptions)(options.sfc.script, options.scriptRanges); | ||
if (options.sfc.script && options.scriptRanges?.exportDefault?.args) { | ||
const { args } = options.scriptRanges.exportDefault; | ||
yield (0, common_1.generateSfcBlockSection)(options.sfc.script, args.start + 1, args.end - 1, index_1.codeFeatures.all); | ||
} | ||
@@ -51,0 +59,0 @@ yield `})${common_1.endOfLine}`; // defineComponent { |
@@ -45,16 +45,19 @@ "use strict"; | ||
+ ` __VLS_props: NonNullable<Awaited<typeof __VLS_setup>>['props'],${common_1.newLine}` | ||
+ ` __VLS_ctx?: ${ctx.helperTypes.Prettify.name}<Pick<NonNullable<Awaited<typeof __VLS_setup>>, 'attrs' | 'emit' | 'slots'>>,${common_1.newLine}` // use __VLS_Prettify for less dts code | ||
+ ` __VLS_ctx?: ${ctx.localTypes.PrettifyLocal}<Pick<NonNullable<Awaited<typeof __VLS_setup>>, 'attrs' | 'emit' | 'slots'>>,${common_1.newLine}` // use __VLS_Prettify for less dts code | ||
+ ` __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>['expose'],${common_1.newLine}` | ||
+ ` __VLS_setup = (async () => {${common_1.newLine}`; | ||
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, undefined, definePropMirrors); | ||
const emitTypes = ['__VLS_ModelEmitsType']; | ||
const emitTypes = []; | ||
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 {${common_1.newLine}` | ||
+ ` props: ${ctx.helperTypes.Prettify.name}<typeof __VLS_functionalComponentProps & __VLS_PublicProps> & __VLS_BuiltInPublicProps,${common_1.newLine}` | ||
+ ` props: ${ctx.localTypes.PrettifyLocal}<typeof __VLS_functionalComponentProps & __VLS_PublicProps> & __VLS_BuiltInPublicProps,${common_1.newLine}` | ||
+ ` expose(exposed: import('${options.vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.expose.define ? 'typeof __VLS_exposed' : '{}'}>): void,${common_1.newLine}` | ||
+ ` attrs: any,${common_1.newLine}` | ||
+ ` slots: ReturnType<typeof __VLS_template>,${common_1.newLine}` | ||
+ ` emit: ${emitTypes.join(' & ')},${common_1.newLine}` | ||
+ ` slots: __VLS_Slots,${common_1.newLine}` | ||
+ ` emit: ${emitTypes.length ? emitTypes.join(' & ') : `{}`},${common_1.newLine}` | ||
+ ` }${common_1.endOfLine}`; | ||
@@ -78,12 +81,12 @@ yield ` })(),${common_1.newLine}`; // __VLS_setup = (async () => { | ||
for (const defineProp of scriptSetupRanges.defineProp) { | ||
if (!defineProp.name) { | ||
if (!defineProp.localName) { | ||
continue; | ||
} | ||
const propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end); | ||
const propMirror = definePropMirrors.get(propName); | ||
const [_, localName] = getPropAndLocalName(scriptSetup, defineProp); | ||
const propMirror = definePropMirrors.get(localName); | ||
if (propMirror !== undefined) { | ||
options.linkedCodeMappings.push({ | ||
sourceOffsets: [defineProp.name.start + ctx.scriptSetupGeneratedOffset], | ||
sourceOffsets: [defineProp.localName.start + ctx.scriptSetupGeneratedOffset], | ||
generatedOffsets: [propMirror], | ||
lengths: [defineProp.name.end - defineProp.name.start], | ||
lengths: [defineProp.localName.end - defineProp.localName.start], | ||
data: undefined, | ||
@@ -99,3 +102,3 @@ }); | ||
for (const macro of Object.keys(options.vueCompilerOptions.macros)) { | ||
if (!ctx.bindingNames.has(macro)) { | ||
if (!ctx.bindingNames.has(macro) && macro !== 'templateRef') { | ||
yield macro + `, `; | ||
@@ -194,2 +197,35 @@ } | ||
} | ||
if (scriptSetupRanges.cssModules.length) { | ||
for (const { exp, arg } of scriptSetupRanges.cssModules) { | ||
if (arg) { | ||
setupCodeModifies.push([ | ||
[ | ||
` as Omit<__VLS_StyleModules, '$style'>[`, | ||
(0, common_1.generateSfcBlockSection)(scriptSetup, arg.start, arg.end, index_1.codeFeatures.all), | ||
`]` | ||
], | ||
exp.end, | ||
exp.end | ||
]); | ||
} | ||
else { | ||
setupCodeModifies.push([ | ||
[ | ||
` as __VLS_StyleModules[`, | ||
['', scriptSetup.name, exp.start, index_1.codeFeatures.verification], | ||
`'$style'`, | ||
['', scriptSetup.name, exp.end, index_1.codeFeatures.verification], | ||
`]` | ||
], | ||
exp.end, | ||
exp.end | ||
]); | ||
} | ||
} | ||
} | ||
for (const { define } of scriptSetupRanges.templateRefs) { | ||
if (define?.arg) { | ||
setupCodeModifies.push([[`<__VLS_Refs[${scriptSetup.content.slice(define.arg.start, define.arg.end)}], keyof __VLS_Refs>`], define.arg.start - 1, define.arg.start - 1]); | ||
} | ||
} | ||
setupCodeModifies = setupCodeModifies.sort((a, b) => a[1] - b[1]); | ||
@@ -223,3 +259,6 @@ if (setupCodeModifies.length) { | ||
yield* generateModelEmits(options, scriptSetup, scriptSetupRanges); | ||
yield* generateStyleModules(options, ctx); | ||
yield* (0, template_1.generateTemplate)(options, ctx, false); | ||
yield `type __VLS_Refs = typeof __VLS_templateResult['refs']${common_1.endOfLine}`; | ||
yield `type __VLS_Slots = typeof __VLS_templateResult['slots']${common_1.endOfLine}`; | ||
if (syntax) { | ||
@@ -231,3 +270,3 @@ if (!options.vueCompilerOptions.skipTemplateCodegen && (options.templateCodegen?.hasSlot || scriptSetupRanges?.slots.define)) { | ||
yield `${syntax} `; | ||
yield `{} as ${ctx.helperTypes.WithTemplateSlots.name}<typeof __VLS_component, ReturnType<typeof __VLS_template>>${common_1.endOfLine}`; | ||
yield `{} as ${ctx.localTypes.WithTemplateSlots}<typeof __VLS_component, __VLS_Slots>${common_1.endOfLine}`; | ||
} | ||
@@ -242,6 +281,5 @@ else { | ||
function* generateComponentProps(options, ctx, scriptSetup, scriptSetupRanges, definePropMirrors) { | ||
yield `const __VLS_fnComponent = ` | ||
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${common_1.newLine}`; | ||
yield `const __VLS_fnComponent = (await import('${options.vueCompilerOptions.lib}')).defineComponent({${common_1.newLine}`; | ||
if (scriptSetupRanges.props.define?.arg) { | ||
yield ` props: `; | ||
yield `props: `; | ||
yield (0, common_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, index_1.codeFeatures.navigation); | ||
@@ -261,3 +299,3 @@ yield `,${common_1.newLine}`; | ||
yield `let __VLS_functionalComponentProps!: `; | ||
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`; | ||
yield `${ctx.localTypes.OmitKeepDiscriminatedUnion}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`; | ||
yield common_1.endOfLine; | ||
@@ -268,10 +306,14 @@ if (scriptSetupRanges.defineProp.length) { | ||
if (defineProp.defaultValue) { | ||
if (defineProp.name) { | ||
yield scriptSetup.content.substring(defineProp.name.start, defineProp.name.end); | ||
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp); | ||
if (defineProp.name || defineProp.isModel) { | ||
yield propName; | ||
} | ||
else if (defineProp.localName) { | ||
yield localName; | ||
} | ||
else { | ||
yield `modelValue`; | ||
continue; | ||
} | ||
yield `: `; | ||
yield scriptSetup.content.substring(defineProp.defaultValue.start, defineProp.defaultValue.end); | ||
yield getRangeName(scriptSetup, defineProp.defaultValue); | ||
yield `,${common_1.newLine}`; | ||
@@ -288,3 +330,3 @@ } | ||
ctx.generatedPropsType = true; | ||
yield `${ctx.helperTypes.PropsChildren.name}<typeof __VLS_slots>`; | ||
yield `${ctx.localTypes.PropsChildren}<typeof __VLS_slots>`; | ||
} | ||
@@ -298,16 +340,16 @@ if (scriptSetupRanges.defineProp.length) { | ||
for (const defineProp of scriptSetupRanges.defineProp) { | ||
let propName = 'modelValue'; | ||
if (defineProp.name && defineProp.nameIsString) { | ||
const [propName, localName] = getPropAndLocalName(scriptSetup, defineProp); | ||
if (defineProp.isModel && !defineProp.name) { | ||
yield propName; | ||
} | ||
else if (defineProp.name) { | ||
// renaming support | ||
yield (0, common_1.generateSfcBlockSection)(scriptSetup, defineProp.name.start, defineProp.name.end, index_1.codeFeatures.navigation); | ||
propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end); | ||
propName = propName.replace(/['"]+/g, ''); | ||
} | ||
else if (defineProp.name) { | ||
propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end); | ||
definePropMirrors.set(propName, options.getGeneratedLength()); | ||
yield propName; | ||
else if (defineProp.localName) { | ||
definePropMirrors.set(localName, options.getGeneratedLength()); | ||
yield localName; | ||
} | ||
else { | ||
yield propName; | ||
continue; | ||
} | ||
@@ -317,3 +359,3 @@ yield defineProp.required | ||
: `?: `; | ||
yield* generateDefinePropType(scriptSetup, propName, defineProp); | ||
yield* generateDefinePropType(scriptSetup, propName, localName, defineProp); | ||
yield `,${common_1.newLine}`; | ||
@@ -323,5 +365,5 @@ if (defineProp.modifierType) { | ||
if (defineProp.name) { | ||
propModifierName = `${scriptSetup.content.substring(defineProp.name.start + 1, defineProp.name.end - 1)}Modifiers`; | ||
propModifierName = `${getRangeName(scriptSetup, defineProp.name, true)}Modifiers`; | ||
} | ||
const modifierType = scriptSetup.content.substring(defineProp.modifierType.start, defineProp.modifierType.end); | ||
const modifierType = getRangeName(scriptSetup, defineProp.modifierType); | ||
definePropMirrors.set(propModifierName, options.getGeneratedLength()); | ||
@@ -346,42 +388,64 @@ yield `${propModifierName}?: Record<${modifierType}, true>,${common_1.endOfLine}`; | ||
function* generateModelEmits(options, scriptSetup, scriptSetupRanges) { | ||
yield `type __VLS_ModelEmitsType = `; | ||
if (scriptSetupRanges.defineProp.filter(p => p.isModel).length) { | ||
if (options.vueCompilerOptions.target < 3.5) { | ||
yield `typeof __VLS_modelEmitsType${common_1.endOfLine}`; | ||
yield `const __VLS_modelEmitsType = (await import('${options.vueCompilerOptions.lib}')).defineEmits<`; | ||
} | ||
yield `{${common_1.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 `]${common_1.endOfLine}`; | ||
} | ||
let propName = 'modelValue'; | ||
if (defineProp.name) { | ||
propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end); | ||
propName = propName.replace(/['"]+/g, ''); | ||
} | ||
yield `'update:${propName}': [${propName}:`; | ||
yield* generateDefinePropType(scriptSetup, propName, defineProp); | ||
yield `]${common_1.endOfLine}`; | ||
}; | ||
if (options.vueCompilerOptions.target >= 3.5) { | ||
yield `type __VLS_ModelEmitsType = {${common_1.newLine}`; | ||
yield* generateDefineModels(); | ||
yield `}${common_1.endOfLine}`; | ||
} | ||
yield `}`; | ||
if (options.vueCompilerOptions.target < 3.5) { | ||
yield `>()`; | ||
else { | ||
yield `const __VLS_modelEmitsType = (await import('${options.vueCompilerOptions.lib}')).defineEmits<{${common_1.newLine}`; | ||
yield* generateDefineModels(); | ||
yield `}>()${common_1.endOfLine}`; | ||
yield `type __VLS_ModelEmitsType = typeof __VLS_modelEmitsType${common_1.endOfLine}`; | ||
} | ||
} | ||
else { | ||
yield `{}`; | ||
} | ||
function* generateStyleModules(options, ctx) { | ||
const styles = options.sfc.styles.filter(style => style.module); | ||
if (!styles.length) { | ||
return; | ||
} | ||
yield `type __VLS_StyleModules = {${common_1.newLine}`; | ||
for (let i = 0; i < styles.length; i++) { | ||
const style = styles[i]; | ||
const { name, offset } = style.module; | ||
if (offset) { | ||
yield [ | ||
name, | ||
'main', | ||
offset + 1, | ||
index_1.codeFeatures.all | ||
]; | ||
} | ||
else { | ||
yield name; | ||
} | ||
yield `: Record<string, string> & ${ctx.localTypes.PrettifyLocal}<{}`; | ||
for (const className of style.classNames) { | ||
yield* (0, template_1.generateCssClassProperty)(i, className.text, className.offset, 'string', false); | ||
} | ||
yield `>${common_1.endOfLine}`; | ||
} | ||
yield `}`; | ||
yield common_1.endOfLine; | ||
} | ||
function* generateDefinePropType(scriptSetup, propName, defineProp) { | ||
function* generateDefinePropType(scriptSetup, propName, localName, defineProp) { | ||
if (defineProp.type) { | ||
// Infer from defineProp<T> | ||
yield scriptSetup.content.substring(defineProp.type.start, defineProp.type.end); | ||
yield getRangeName(scriptSetup, defineProp.type); | ||
} | ||
else if ((defineProp.name && defineProp.nameIsString) || !defineProp.nameIsString) { | ||
else if (defineProp.runtimeType && localName) { | ||
// Infer from actual prop declaration code | ||
yield `NonNullable<typeof ${propName}['value']>`; | ||
yield `typeof ${localName}['value']`; | ||
} | ||
else if (defineProp.defaultValue) { | ||
else if (defineProp.defaultValue && propName) { | ||
// Infer from defineProp({default: T}) | ||
@@ -394,2 +458,20 @@ yield `typeof __VLS_defaults['${propName}']`; | ||
} | ||
function getPropAndLocalName(scriptSetup, defineProp) { | ||
const localName = defineProp.localName | ||
? getRangeName(scriptSetup, defineProp.localName) | ||
: undefined; | ||
let propName = defineProp.name | ||
? getRangeName(scriptSetup, defineProp.name) | ||
: defineProp.isModel | ||
? 'modelValue' | ||
: localName; | ||
if (defineProp.name) { | ||
propName = propName.replace(/['"]+/g, ''); | ||
} | ||
return [propName, localName]; | ||
} | ||
function getRangeName(scriptSetup, range, unwrap = false) { | ||
const offset = unwrap ? 1 : 0; | ||
return scriptSetup.content.substring(range.start + offset, range.end - offset); | ||
} | ||
//# sourceMappingURL=scriptSetup.js.map |
import type { Code } from '../../types'; | ||
import type { ScriptCodegenContext } from './context'; | ||
import { type ScriptCodegenOptions } from './index'; | ||
export declare function generateTemplateCtx(options: ScriptCodegenOptions, isClassComponent: boolean): Generator<Code>; | ||
export declare function generateTemplateComponents(options: ScriptCodegenOptions): Generator<Code>; | ||
export declare function generateTemplate(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, isClassComponent: boolean): Generator<Code>; | ||
export declare function generateCssClassProperty(styleIndex: number, classNameWithDot: string, offset: number, propertyType: string, optional: boolean): Generator<Code>; | ||
export declare function getTemplateUsageVars(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Set<string>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateTemplateCtx = generateTemplateCtx; | ||
exports.generateTemplateComponents = generateTemplateComponents; | ||
exports.generateTemplate = generateTemplate; | ||
exports.generateCssClassProperty = generateCssClassProperty; | ||
exports.getTemplateUsageVars = getTemplateUsageVars; | ||
@@ -9,36 +12,26 @@ const shared_1 = require("../../utils/shared"); | ||
const interpolation_1 = require("../template/interpolation"); | ||
const styleScopedClasses_1 = require("../template/styleScopedClasses"); | ||
const index_1 = require("./index"); | ||
const internalComponent_1 = require("./internalComponent"); | ||
function* generateTemplate(options, ctx, isClassComponent) { | ||
ctx.generatedTemplate = true; | ||
if (!options.vueCompilerOptions.skipTemplateCodegen) { | ||
if (isClassComponent) { | ||
yield `__VLS_template() {${common_1.newLine}`; | ||
} | ||
else { | ||
yield `function __VLS_template() {${common_1.newLine}`; | ||
} | ||
const templateCodegenCtx = (0, context_1.createTemplateCodegenContext)(new Set()); | ||
yield* generateCtx(options, ctx, isClassComponent); | ||
yield* generateTemplateContext(options, templateCodegenCtx); | ||
yield* generateExportOptions(options); | ||
yield* generateConstNameOption(options); | ||
yield* (0, internalComponent_1.generateInternalComponent)(options, ctx, templateCodegenCtx); | ||
yield `}${common_1.newLine}`; | ||
function* generateTemplateCtx(options, isClassComponent) { | ||
const types = []; | ||
if (isClassComponent) { | ||
types.push(`typeof this`); | ||
} | ||
else { | ||
yield `function __VLS_template() {${common_1.newLine}`; | ||
const templateUsageVars = [...getTemplateUsageVars(options, ctx)]; | ||
yield `// @ts-ignore${common_1.newLine}`; | ||
yield `[${templateUsageVars.join(', ')}]${common_1.newLine}`; | ||
yield `return {}${common_1.endOfLine}`; | ||
yield `}${common_1.newLine}`; | ||
types.push(`InstanceType<__VLS_PickNotAny<typeof __VLS_internalComponent, new () => {}>>`); | ||
} | ||
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(' & ')}${common_1.endOfLine}`; | ||
} | ||
function* generateExportOptions(options) { | ||
yield common_1.newLine; | ||
yield `const __VLS_componentsOption = `; | ||
function* generateTemplateComponents(options) { | ||
const exps = []; | ||
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), | ||
@@ -48,61 +41,54 @@ 'script', | ||
index_1.codeFeatures.navigation, | ||
]; | ||
]); | ||
} | ||
else { | ||
yield `{}`; | ||
} | ||
yield common_1.endOfLine; | ||
} | ||
function* generateConstNameOption(options) { | ||
let nameType; | ||
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 common_1.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('.'))}'${common_1.endOfLine}`; | ||
nameType = 'typeof __VLS_name'; | ||
} | ||
else { | ||
yield `const __VLS_name = undefined${common_1.endOfLine}`; | ||
if (nameType) { | ||
exps.push(`{} as { | ||
[K in ${nameType}]: typeof __VLS_internalComponent | ||
& (new () => { | ||
${(0, shared_1.getSlotsPropertyName)(options.vueCompilerOptions.target)}: typeof ${options.scriptSetupRanges?.slots?.name ?? '__VLS_slots'} | ||
}) | ||
}`); | ||
} | ||
exps.push(`{} as NonNullable<typeof __VLS_internalComponent extends { components: infer C } ? C : {}>`); | ||
exps.push(`{} as __VLS_GlobalComponents`); | ||
exps.push(`{} as typeof __VLS_ctx`); | ||
yield `const __VLS_components = {${common_1.newLine}`; | ||
for (const type of exps) { | ||
yield `...`; | ||
yield type; | ||
yield `,${common_1.newLine}`; | ||
} | ||
yield `}${common_1.endOfLine}`; | ||
} | ||
function* generateCtx(options, ctx, isClassComponent) { | ||
yield `let __VLS_ctx!: `; | ||
if (options.vueCompilerOptions.petiteVueExtensions.some(ext => options.fileBaseName.endsWith(ext))) { | ||
yield `typeof globalThis & `; | ||
function* generateTemplate(options, ctx, isClassComponent) { | ||
ctx.generatedTemplate = true; | ||
if (!options.vueCompilerOptions.skipTemplateCodegen) { | ||
const templateCodegenCtx = (0, context_1.createTemplateCodegenContext)({ | ||
scriptSetupBindingNames: new Set(), | ||
edited: options.edited, | ||
}); | ||
yield* generateTemplateCtx(options, isClassComponent); | ||
yield* generateTemplateComponents(options); | ||
yield* generateTemplateBody(options, ctx, templateCodegenCtx); | ||
yield* (0, internalComponent_1.generateInternalComponent)(options, ctx, templateCodegenCtx); | ||
} | ||
if (!isClassComponent) { | ||
yield `InstanceType<__VLS_PickNotAny<typeof __VLS_internalComponent, new () => {}>>`; | ||
} | ||
else { | ||
yield `typeof this`; | ||
const templateUsageVars = [...getTemplateUsageVars(options, ctx)]; | ||
yield `// @ts-ignore${common_1.newLine}`; | ||
yield `[${templateUsageVars.join(', ')}]${common_1.newLine}`; | ||
yield `const __VLS_templateResult { slots: {}, refs: {}, attrs: {} }${common_1.endOfLine}`; | ||
} | ||
/* CSS Module */ | ||
if (options.sfc.styles.some(style => style.module)) { | ||
yield `& {${common_1.newLine}`; | ||
for (let i = 0; i < options.sfc.styles.length; i++) { | ||
const style = options.sfc.styles[i]; | ||
if (style.module) { | ||
yield `${style.module}: Record<string, string> & ${ctx.helperTypes.Prettify.name}<{}`; | ||
for (const className of style.classNames) { | ||
yield* generateCssClassProperty(i, className.text, className.offset, 'string', false); | ||
} | ||
yield `>${common_1.endOfLine}`; | ||
} | ||
} | ||
yield `}`; | ||
} | ||
yield common_1.endOfLine; | ||
} | ||
function* generateTemplateContext(options, templateCodegenCtx) { | ||
/* Components */ | ||
yield `/* Components */${common_1.newLine}`; | ||
yield `let __VLS_otherComponents!: NonNullable<typeof __VLS_internalComponent extends { components: infer C } ? C : {}> & typeof __VLS_componentsOption${common_1.endOfLine}`; | ||
yield `let __VLS_own!: __VLS_SelfComponent<typeof __VLS_name, typeof __VLS_internalComponent & (new () => { ${(0, shared_1.getSlotsPropertyName)(options.vueCompilerOptions.target)}: typeof ${options.scriptSetupRanges?.slots?.name ?? '__VLS_slots'} })>${common_1.endOfLine}`; | ||
yield `let __VLS_localComponents!: typeof __VLS_otherComponents & Omit<typeof __VLS_own, keyof typeof __VLS_otherComponents>${common_1.endOfLine}`; | ||
yield `let __VLS_components!: typeof __VLS_localComponents & __VLS_GlobalComponents & typeof __VLS_ctx${common_1.endOfLine}`; // for html completion, TS references... | ||
/* Style Scoped */ | ||
yield `/* Style Scoped */${common_1.newLine}`; | ||
yield `type __VLS_StyleScopedClasses = {}`; | ||
function* generateTemplateBody(options, ctx, templateCodegenCtx) { | ||
const firstClasses = new Set(); | ||
yield `let __VLS_styleScopedClasses!: {}`; | ||
for (let i = 0; i < options.sfc.styles.length; i++) { | ||
@@ -113,2 +99,11 @@ const style = options.sfc.styles[i]; | ||
for (const className of style.classNames) { | ||
if (firstClasses.has(className.text)) { | ||
templateCodegenCtx.scopedClasses.push({ | ||
source: 'style_' + i, | ||
className: className.text.slice(1), | ||
offset: className.offset + 1 | ||
}); | ||
continue; | ||
} | ||
firstClasses.add(className.text); | ||
yield* generateCssClassProperty(i, className.text, className.offset, 'boolean', true); | ||
@@ -119,3 +114,3 @@ } | ||
yield common_1.endOfLine; | ||
yield `let __VLS_styleScopedClasses!: __VLS_StyleScopedClasses | keyof __VLS_StyleScopedClasses | (keyof __VLS_StyleScopedClasses)[]${common_1.endOfLine}`; | ||
yield* (0, styleScopedClasses_1.generateStyleScopedClasses)(templateCodegenCtx, true); | ||
yield* generateCssVars(options, templateCodegenCtx); | ||
@@ -131,5 +126,11 @@ if (options.templateCodegen) { | ||
yield `const __VLS_slots = {}${common_1.endOfLine}`; | ||
yield `const __VLS_refs = {}${common_1.endOfLine}`; | ||
yield `const __VLS_inheritedAttrs = {}${common_1.endOfLine}`; | ||
} | ||
} | ||
yield `return ${options.scriptSetupRanges?.slots.name ?? '__VLS_slots'}${common_1.endOfLine}`; | ||
yield `const __VLS_templateResult = {`; | ||
yield `slots: ${options.scriptSetupRanges?.slots.name ?? '__VLS_slots'},${common_1.newLine}`; | ||
yield `refs: __VLS_refs as ${ctx.localTypes.PickRefsExpose}<typeof __VLS_refs>,${common_1.newLine}`; | ||
yield `attrs: {} as Partial<typeof __VLS_inheritedAttrs>,${common_1.newLine}`; | ||
yield `}${common_1.endOfLine}`; | ||
} | ||
@@ -142,3 +143,3 @@ function* generateCssClassProperty(styleIndex, classNameWithDot, offset, propertyType, optional) { | ||
offset, | ||
index_1.codeFeatures.navigationWithoutRename, | ||
index_1.codeFeatures.navigation, | ||
]; | ||
@@ -145,0 +146,0 @@ yield `'`; |
import type * as CompilerDOM from '@vue/compiler-dom'; | ||
import type { Code, VueCodeInformation } from '../../types'; | ||
import type { TemplateCodegenOptions } from './index'; | ||
import { InlayHintInfo } from '../types'; | ||
export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>; | ||
export declare function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCodegenOptions['scriptSetupBindingNames']): { | ||
export declare function createTemplateCodegenContext(options: Pick<TemplateCodegenOptions, 'scriptSetupBindingNames' | 'edited'>): { | ||
slots: { | ||
@@ -35,2 +36,3 @@ name: string; | ||
scopedClasses: { | ||
source: string; | ||
className: string; | ||
@@ -40,3 +42,6 @@ offset: number; | ||
emptyClassOffsets: number[]; | ||
inlayHints: InlayHintInfo[]; | ||
hasSlot: boolean; | ||
inheritedAttrVars: Set<unknown>; | ||
singleRootNode: CompilerDOM.ElementNode | undefined; | ||
accessExternalVariable(name: string, offset?: number): void; | ||
@@ -43,0 +48,0 @@ hasLocalVariable: (name: string) => boolean; |
@@ -55,3 +55,3 @@ "use strict"; | ||
}; | ||
function createTemplateCodegenContext(scriptSetupBindingNames) { | ||
function createTemplateCodegenContext(options) { | ||
let ignoredError = false; | ||
@@ -98,2 +98,3 @@ let expectErrorToken; | ||
const emptyClassOffsets = []; | ||
const inlayHints = []; | ||
return { | ||
@@ -109,3 +110,6 @@ slots, | ||
emptyClassOffsets, | ||
inlayHints, | ||
hasSlot: false, | ||
inheritedAttrVars: new Set(), | ||
singleRootNode: undefined, | ||
accessExternalVariable(name, offset) { | ||
@@ -165,2 +169,5 @@ let arr = accessExternalVariables.get(name); | ||
generateAutoImportCompletion: function* () { | ||
if (!options.edited) { | ||
return; | ||
} | ||
const all = [...accessExternalVariables.entries()]; | ||
@@ -174,3 +181,3 @@ if (!all.some(([_, offsets]) => offsets.size)) { | ||
for (const offset of offsets) { | ||
if (scriptSetupBindingNames.has(varName)) { | ||
if (options.scriptSetupBindingNames.has(varName)) { | ||
// #3409 | ||
@@ -177,0 +184,0 @@ yield [ |
@@ -5,5 +5,5 @@ import * as CompilerDOM from '@vue/compiler-dom'; | ||
import type { TemplateCodegenOptions } from './index'; | ||
export declare function generateComponent(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, currentComponent: CompilerDOM.ElementNode | undefined, componentCtxVar: string | undefined): Generator<Code>; | ||
export declare function generateComponent(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, currentComponent: CompilerDOM.ElementNode | undefined): Generator<Code>; | ||
export declare function generateElement(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, currentComponent: CompilerDOM.ElementNode | undefined, componentCtxVar: string | undefined): Generator<Code>; | ||
export declare function getCanonicalComponentName(tagText: string): string; | ||
export declare function getPossibleOriginalComponentNames(tagText: string, deduplicate: boolean): string[]; |
@@ -20,7 +20,8 @@ "use strict"; | ||
const objectProperty_1 = require("./objectProperty"); | ||
const scriptSetupRanges_1 = require("../../parsers/scriptSetupRanges"); | ||
const colonReg = /:/g; | ||
function* generateComponent(options, ctx, node, currentComponent, componentCtxVar) { | ||
function* generateComponent(options, ctx, node, currentComponent) { | ||
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; | ||
const tagOffsets = endTagOffset !== undefined | ||
const tagOffsets = endTagOffset !== undefined && endTagOffset > startTagOffset | ||
? [startTagOffset, endTagOffset] | ||
@@ -45,3 +46,3 @@ : [startTagOffset]; | ||
exp: prop.exp.loc.source, | ||
offset: prop.exp.loc.start.offset, | ||
offsets: [prop.exp.loc.start.offset, undefined], | ||
astHolder: prop.exp.loc, | ||
@@ -59,3 +60,3 @@ }; | ||
astHolder: node.loc, | ||
offset: startTagOffset, | ||
offsets: [startTagOffset, endTagOffset], | ||
}; | ||
@@ -90,30 +91,29 @@ } | ||
else if (dynamicTagInfo) { | ||
yield `const ${var_originalComponent} = `; | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, dynamicTagInfo.exp, dynamicTagInfo.astHolder, dynamicTagInfo.offset, ctx.codeFeatures.all, '(', ')'); | ||
yield common_1.endOfLine; | ||
yield `const ${var_originalComponent} = (`; | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, dynamicTagInfo.exp, dynamicTagInfo.astHolder, dynamicTagInfo.offsets[0], ctx.codeFeatures.all, '(', ')'); | ||
if (dynamicTagInfo.offsets[1] !== undefined) { | ||
yield `,`; | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, dynamicTagInfo.exp, dynamicTagInfo.astHolder, dynamicTagInfo.offsets[1], { | ||
...ctx.codeFeatures.all, | ||
completion: false, | ||
}, '(', ')'); | ||
} | ||
yield `)${common_1.endOfLine}`; | ||
} | ||
else if (!isComponentTag) { | ||
yield `// @ts-ignore${common_1.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* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, componentName); | ||
yield ` }: `; | ||
} | ||
yield `typeof __VLS_resolvedLocalAndGlobalComponents)${common_1.newLine}`; | ||
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, getCanonicalComponentName(node.tag), startTagOffset, ctx.codeFeatures.verification); | ||
yield common_1.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 common_1.endOfLine; | ||
} | ||
yield `const ${var_originalComponent} = __VLS_resolvedLocalAndGlobalComponents.`; | ||
yield* generateCanonicalComponentName(node.tag, startTagOffset, { | ||
// with hover support | ||
...ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation, | ||
...ctx.codeFeatures.verification, | ||
}); | ||
yield `${common_1.endOfLine}`; | ||
const camelizedTag = (0, shared_1.camelize)(node.tag); | ||
if (common_1.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 ? (0, shared_1.capitalize)(camelizedTag) : camelizedTag; | ||
yield `__VLS_components.`; | ||
yield `typeof __VLS_components.`; | ||
yield* (0, camelized_1.generateCamelized)(shouldCapitalize ? (0, shared_1.capitalize)(node.tag) : node.tag, tagOffset, { | ||
@@ -125,11 +125,10 @@ navigation: { | ||
}); | ||
yield `;`; | ||
yield `, `; | ||
} | ||
} | ||
yield `${common_1.newLine}`; | ||
yield `] } */${common_1.newLine}`; | ||
// auto import support | ||
yield `// @ts-ignore${common_1.newLine}`; // #2304 | ||
yield `[`; | ||
for (const tagOffset of tagOffsets) { | ||
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(node.tag), tagOffset, { | ||
if (options.edited) { | ||
yield `// @ts-ignore${common_1.newLine}`; // #2304 | ||
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(node.tag), startTagOffset, { | ||
completion: { | ||
@@ -140,5 +139,4 @@ isAdditional: true, | ||
}); | ||
yield `,`; | ||
yield `${common_1.endOfLine}`; | ||
} | ||
yield `]${common_1.endOfLine}`; | ||
} | ||
@@ -153,19 +151,5 @@ } | ||
yield `}))${common_1.endOfLine}`; | ||
if (options.vueCompilerOptions.strictTemplates) { | ||
// with strictTemplates, generate once for props type-checking + instance type | ||
yield `const ${var_componentInstance} = ${var_functionalComponent}(`; | ||
yield* (0, common_1.wrapWith)(startTagOffset, startTagOffset + node.tag.length, ctx.codeFeatures.verification, `{`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, true, propsFailedExps), `}`); | ||
yield `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${common_1.endOfLine}`; | ||
} | ||
else { | ||
// without strictTemplates, this only for instacne type | ||
yield `const ${var_componentInstance} = ${var_functionalComponent}({`; | ||
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, props, false); | ||
yield `}, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${common_1.endOfLine}`; | ||
// and this for props type-checking | ||
yield `({} as (props: __VLS_FunctionalComponentProps<typeof ${var_originalComponent}, typeof ${var_componentInstance}> & Record<string, unknown>) => void)(`; | ||
yield* (0, common_1.wrapWith)(startTagOffset, startTagOffset + node.tag.length, ctx.codeFeatures.verification, `{`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, true, propsFailedExps), `}`); | ||
yield `)${common_1.endOfLine}`; | ||
} | ||
componentCtxVar = var_defineComponentCtx; | ||
yield `const ${var_componentInstance} = ${var_functionalComponent}(`; | ||
yield* (0, common_1.wrapWith)(startTagOffset, startTagOffset + node.tag.length, ctx.codeFeatures.verification, `{`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, true, propsFailedExps), `}`); | ||
yield `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${common_1.endOfLine}`; | ||
currentComponent = node; | ||
@@ -176,19 +160,41 @@ for (const failedExp of propsFailedExps) { | ||
} | ||
yield* generateVScope(options, ctx, node, props); | ||
ctx.usedComponentCtxVars.add(componentCtxVar); | ||
const refName = yield* generateVScope(options, ctx, node, props); | ||
if (refName) { | ||
ctx.usedComponentCtxVars.add(var_defineComponentCtx); | ||
} | ||
const usedComponentEventsVar = yield* (0, elementEvents_1.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}))${common_1.endOfLine}`; | ||
} | ||
if (usedComponentEventsVar) { | ||
yield `let ${var_componentEmit}!: typeof ${componentCtxVar}.emit${common_1.endOfLine}`; | ||
ctx.usedComponentCtxVars.add(var_defineComponentCtx); | ||
yield `let ${var_componentEmit}!: typeof ${var_defineComponentCtx}.emit${common_1.endOfLine}`; | ||
yield `let ${var_componentEvents}!: __VLS_NormalizeEmits<typeof ${var_componentEmit}>${common_1.endOfLine}`; | ||
} | ||
if (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); | ||
yield `var ${varAttrs}!: Parameters<typeof ${var_functionalComponent}>[0];\n`; | ||
} | ||
const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot'); | ||
if (slotDir) { | ||
yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, componentCtxVar); | ||
yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, var_defineComponentCtx); | ||
} | ||
else { | ||
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node, currentComponent, componentCtxVar); | ||
yield* (0, elementChildren_1.generateElementChildren)(options, ctx, node, currentComponent, var_defineComponentCtx); | ||
} | ||
if (ctx.usedComponentCtxVars.has(var_defineComponentCtx)) { | ||
yield `const ${var_defineComponentCtx} = __VLS_pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance})${common_1.endOfLine}`; | ||
if (refName) { | ||
yield `// @ts-ignore${common_1.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 common_1.endOfLine; | ||
} | ||
} | ||
} | ||
@@ -214,3 +220,9 @@ function* generateElement(options, ctx, node, currentComponent, componentCtxVar) { | ||
} | ||
yield* generateVScope(options, ctx, node, node.props); | ||
const refName = yield* generateVScope(options, ctx, node, node.props); | ||
if (refName) { | ||
yield `// @ts-ignore${common_1.newLine}`; | ||
yield `${refName} = __VLS_intrinsicElements`; | ||
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, node.tag); | ||
yield common_1.endOfLine; | ||
} | ||
const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot'); | ||
@@ -223,2 +235,7 @@ if (slotDir && componentCtxVar) { | ||
} | ||
if (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}`); | ||
} | ||
} | ||
@@ -245,4 +262,4 @@ function* generateVScope(options, ctx, node, props) { | ||
yield* (0, elementDirectives_1.generateElementDirectives)(options, ctx, node); | ||
yield* generateReferencesForElements(options, ctx, node); // <el ref="foo" /> | ||
yield* generateReferencesForScopedCssClasses(ctx, node); | ||
const refName = yield* generateReferencesForElements(options, ctx, node); // <el ref="foo" /> | ||
yield* generateReferencesForScopedCssClasses(options, ctx, node); | ||
if (inScope) { | ||
@@ -252,2 +269,3 @@ yield `}${common_1.newLine}`; | ||
} | ||
return refName; | ||
} | ||
@@ -289,3 +307,3 @@ function getCanonicalComponentName(tagText) { | ||
if (slotDir?.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && slotDir.arg.content) { | ||
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slotDir.arg.loc.source, slotDir.arg.loc.start.offset, slotDir.arg.isStatic ? ctx.codeFeatures.withoutHighlight : ctx.codeFeatures.all, slotDir.arg.loc); | ||
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slotDir.arg.loc.source, slotDir.arg.loc.start.offset, slotDir.arg.isStatic ? ctx.codeFeatures.withoutHighlight : ctx.codeFeatures.all, slotDir.arg.loc, false, true); | ||
yield ': __VLS_thisSlot'; | ||
@@ -363,9 +381,17 @@ } | ||
&& prop.value) { | ||
const [content, startOffset] = normalizeAttributeValue(prop.value); | ||
yield `// @ts-ignore${common_1.newLine}`; | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, prop.value.content, prop.value.loc, prop.value.loc.start.offset + 1, ctx.codeFeatures.navigation, '(', ')'); | ||
yield `__VLS_ctx`; | ||
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, content, startOffset, ctx.codeFeatures.navigation, prop.value.loc); | ||
yield common_1.endOfLine; | ||
if (common_1.variableNameRegex.test(content)) { | ||
ctx.accessExternalVariable(content, startOffset); | ||
} | ||
const refName = CompilerDOM.toValidAssetId(prop.value.content, '_VLS_refs'); | ||
options.templateRefNames.set(prop.value.content, refName); | ||
return refName; | ||
} | ||
} | ||
} | ||
function* generateReferencesForScopedCssClasses(ctx, node) { | ||
function* generateReferencesForScopedCssClasses(options, ctx, node) { | ||
for (const prop of node.props) { | ||
@@ -375,27 +401,27 @@ if (prop.type === CompilerDOM.NodeTypes.ATTRIBUTE | ||
&& prop.value) { | ||
let startOffset = prop.value.loc.start.offset; | ||
let content = prop.value.loc.source; | ||
if ((content.startsWith(`'`) && content.endsWith(`'`)) | ||
|| (content.startsWith(`"`) && content.endsWith(`"`))) { | ||
startOffset++; | ||
content = content.slice(1, -1); | ||
} | ||
if (content) { | ||
let currentClassName = ''; | ||
for (const char of (content + ' ')) { | ||
if (char.trim() === '') { | ||
if (currentClassName !== '') { | ||
ctx.scopedClasses.push({ className: currentClassName, offset: startOffset }); | ||
startOffset += currentClassName.length; | ||
currentClassName = ''; | ||
} | ||
startOffset += char.length; | ||
if (options.template.lang === 'pug') { | ||
const getClassOffset = Reflect.get(prop.value.loc.start, 'getClassOffset'); | ||
const content = prop.value.loc.source.slice(1, -1); | ||
let startOffset = 1; | ||
for (const className of content.split(' ')) { | ||
if (className) { | ||
ctx.scopedClasses.push({ | ||
source: 'template', | ||
className, | ||
offset: getClassOffset(startOffset), | ||
}); | ||
} | ||
else { | ||
currentClassName += char; | ||
} | ||
startOffset += className.length + 1; | ||
} | ||
} | ||
else { | ||
ctx.emptyClassOffsets.push(startOffset); | ||
let isWrapped = false; | ||
const [content, startOffset] = normalizeAttributeValue(prop.value); | ||
if (content) { | ||
const classes = collectClasses(content, startOffset + (isWrapped ? 1 : 0)); | ||
ctx.scopedClasses.push(...classes); | ||
} | ||
else { | ||
ctx.emptyClassOffsets.push(startOffset); | ||
} | ||
} | ||
@@ -407,10 +433,69 @@ } | ||
&& prop.arg.content === 'class') { | ||
yield `__VLS_styleScopedClasses = (`; | ||
yield [ | ||
prop.exp.content, | ||
'template', | ||
prop.exp.loc.start.offset, | ||
ctx.codeFeatures.navigationAndCompletion, | ||
]; | ||
yield `)${common_1.endOfLine}`; | ||
const content = '`${' + prop.exp.content + '}`'; | ||
const startOffset = prop.exp.loc.start.offset - 3; | ||
const { ts } = options; | ||
const ast = ts.createSourceFile('', content, 99); | ||
const literals = []; | ||
ts.forEachChild(ast, node => { | ||
if (!ts.isExpressionStatement(node) || | ||
!isTemplateExpression(node.expression)) { | ||
return; | ||
} | ||
const expression = node.expression.templateSpans[0].expression; | ||
if (ts.isStringLiteralLike(expression)) { | ||
literals.push(expression); | ||
} | ||
if (ts.isArrayLiteralExpression(expression)) { | ||
walkArrayLiteral(expression); | ||
} | ||
if (ts.isObjectLiteralExpression(expression)) { | ||
walkObjectLiteral(expression); | ||
} | ||
}); | ||
for (const literal of literals) { | ||
const classes = collectClasses(literal.text, literal.end - literal.text.length - 1 + startOffset); | ||
ctx.scopedClasses.push(...classes); | ||
} | ||
function walkArrayLiteral(node) { | ||
const { elements } = node; | ||
for (const element of elements) { | ||
if (ts.isStringLiteralLike(element)) { | ||
literals.push(element); | ||
} | ||
else if (ts.isObjectLiteralExpression(element)) { | ||
walkObjectLiteral(element); | ||
} | ||
} | ||
} | ||
function walkObjectLiteral(node) { | ||
const { properties } = node; | ||
for (const property of properties) { | ||
if (ts.isPropertyAssignment(property)) { | ||
const { name } = property; | ||
if (ts.isIdentifier(name)) { | ||
walkIdentifier(name); | ||
} | ||
else if (ts.isStringLiteral(name)) { | ||
literals.push(name); | ||
} | ||
else if (ts.isComputedPropertyName(name)) { | ||
const { expression } = name; | ||
if (ts.isStringLiteralLike(expression)) { | ||
literals.push(expression); | ||
} | ||
} | ||
} | ||
else if (ts.isShorthandPropertyAssignment(property)) { | ||
walkIdentifier(property.name); | ||
} | ||
} | ||
} | ||
function walkIdentifier(node) { | ||
const text = (0, scriptSetupRanges_1.getNodeText)(ts, node, ast); | ||
ctx.scopedClasses.push({ | ||
source: 'template', | ||
className: text, | ||
offset: node.end - text.length + startOffset | ||
}); | ||
} | ||
} | ||
@@ -425,2 +510,39 @@ } | ||
} | ||
function normalizeAttributeValue(node) { | ||
let offset = node.loc.start.offset; | ||
let content = node.loc.source; | ||
if ((content.startsWith(`'`) && content.endsWith(`'`)) | ||
|| (content.startsWith(`"`) && content.endsWith(`"`))) { | ||
offset++; | ||
content = content.slice(1, -1); | ||
} | ||
return [content, offset]; | ||
} | ||
function collectClasses(content, startOffset = 0) { | ||
const classes = []; | ||
let currentClassName = ''; | ||
let offset = 0; | ||
for (const char of (content + ' ')) { | ||
if (char.trim() === '') { | ||
if (currentClassName !== '') { | ||
classes.push({ | ||
source: 'template', | ||
className: currentClassName, | ||
offset: offset + startOffset | ||
}); | ||
offset += currentClassName.length; | ||
currentClassName = ''; | ||
} | ||
offset += char.length; | ||
} | ||
else { | ||
currentClassName += char; | ||
} | ||
} | ||
return classes; | ||
} | ||
// isTemplateExpression is missing in tsc | ||
function isTemplateExpression(node) { | ||
return node.kind === 228; | ||
} | ||
//# sourceMappingURL=element.js.map |
@@ -21,2 +21,3 @@ "use strict"; | ||
&& node.tagType !== CompilerDOM.ElementTypes.TEMPLATE) { | ||
ctx.usedComponentCtxVars.add(componentCtxVar); | ||
yield `__VLS_nonNullable(${componentCtxVar}.slots).`; | ||
@@ -23,0 +24,0 @@ yield* (0, common_1.wrapWith)(node.children[0].loc.start.offset, node.children[node.children.length - 1].loc.end.offset, ctx.codeFeatures.navigation, `default`); |
@@ -24,3 +24,3 @@ "use strict"; | ||
} | ||
yield* (0, common_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, `__VLS_directiveFunction(__VLS_ctx.`, ...(0, camelized_1.generateCamelized)('v-' + prop.name, prop.loc.start.offset, { | ||
yield* (0, common_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, `__VLS_directiveAsFunction(__VLS_ctx.`, ...(0, camelized_1.generateCamelized)('v-' + prop.name, prop.loc.start.offset, { | ||
...ctx.codeFeatures.all, | ||
@@ -36,5 +36,9 @@ verification: false, | ||
}, | ||
}), `)(`, ...(prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION | ||
? (0, common_1.wrapWith)(prop.exp.loc.start.offset, prop.exp.loc.end.offset, ctx.codeFeatures.verification, ...(0, interpolation_1.generateInterpolation)(options, ctx, prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, ctx.codeFeatures.all, '(', ')')) | ||
: [`undefined`]), `)`); | ||
}), `)(null!, { ...__VLS_directiveBindingRestFields, `, ...(prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION | ||
? [ | ||
...(0, common_1.wrapWith)(prop.exp.loc.start.offset, prop.exp.loc.end.offset, ctx.codeFeatures.verification, 'value'), | ||
': ', | ||
...(0, common_1.wrapWith)(prop.exp.loc.start.offset, prop.exp.loc.end.offset, ctx.codeFeatures.verification, ...(0, interpolation_1.generateInterpolation)(options, ctx, prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, ctx.codeFeatures.all, '(', ')')) | ||
] | ||
: [`undefined`]), `}, null!, null!)`); | ||
yield common_1.endOfLine; | ||
@@ -41,0 +45,0 @@ } |
@@ -108,18 +108,17 @@ "use strict"; | ||
} | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, () => { | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, prop.exp.content, prop.exp.loc, prop.exp.loc.start.offset, offset => { | ||
if (_isCompoundExpression && isFirstMapping) { | ||
isFirstMapping = false; | ||
return { | ||
...ctx.codeFeatures.all, | ||
__hint: { | ||
setting: 'vue.inlayHints.inlineHandlerLeading', | ||
label: '$event =>', | ||
tooltip: [ | ||
'`$event` is a hidden parameter, you can use it in this callback.', | ||
'To hide this hint, set `vue.inlayHints.inlineHandlerLeading` to `false` in IDE settings.', | ||
'[More info](https://github.com/vuejs/language-tools/issues/2445#issuecomment-1444771420)', | ||
].join('\n\n'), | ||
paddingRight: true, | ||
}, | ||
}; | ||
ctx.inlayHints.push({ | ||
blockName: 'template', | ||
offset, | ||
setting: 'vue.inlayHints.inlineHandlerLeading', | ||
label: '$event =>', | ||
paddingRight: true, | ||
tooltip: [ | ||
'`$event` is a hidden parameter, you can use it in this callback.', | ||
'To hide this hint, set `vue.inlayHints.inlineHandlerLeading` to `false` in IDE settings.', | ||
'[More info](https://github.com/vuejs/language-tools/issues/2445#issuecomment-1444771420)', | ||
].join('\n\n'), | ||
}); | ||
} | ||
@@ -126,0 +125,0 @@ return ctx.codeFeatures.all; |
@@ -79,6 +79,19 @@ "use strict"; | ||
} | ||
const codeInfo = ctx.codeFeatures.withoutHighlightAndCompletion; | ||
const codes = (0, common_1.wrapWith)(prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, ...(prop.arg | ||
? (0, objectProperty_1.generateObjectProperty)(options, ctx, 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 | ||
? { | ||
@@ -90,3 +103,3 @@ resolveRenameNewName: shared_1.camelize, | ||
}, prop.loc.name_2 ?? (prop.loc.name_2 = {}), shouldCamelize) | ||
: (0, common_1.wrapWith)(prop.loc.start.offset, prop.loc.start.offset + 'v-model'.length, ctx.codeFeatures.verification, propName)), `: (`, ...genereatePropExp(options, ctx, prop.exp, ctx.codeFeatures.all, prop.arg?.loc.start.offset === prop.exp?.loc.start.offset, enableCodeFeatures), `)`); | ||
: (0, common_1.wrapWith)(prop.loc.start.offset, prop.loc.start.offset + 'v-model'.length, ctx.codeFeatures.verification, propName)), `: (`, ...genereatePropExp(options, ctx, prop, prop.exp, ctx.codeFeatures.all, prop.arg?.loc.start.offset === prop.exp?.loc.start.offset, enableCodeFeatures), `)`); | ||
if (!enableCodeFeatures) { | ||
@@ -118,5 +131,18 @@ yield (0, muggle_string_1.toString)([...codes]); | ||
} | ||
const codeInfo = ctx.codeFeatures.withoutHighlightAndCompletion; | ||
const codes = (0, common_1.conditionWrapWith)(enableCodeFeatures, prop.loc.start.offset, prop.loc.end.offset, ctx.codeFeatures.verification, ...(0, objectProperty_1.generateObjectProperty)(options, ctx, prop.name, 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 | ||
@@ -162,3 +188,3 @@ ? { | ||
} | ||
function* genereatePropExp(options, ctx, exp, features, isShorthand, inlayHints) { | ||
function* genereatePropExp(options, ctx, prop, exp, features, isShorthand, enableCodeFeatures) { | ||
if (exp && exp.constType !== CompilerDOM.ConstantTypes.CAN_STRINGIFY) { // style='z-index: 2' will compile to {'z-index':'2'} | ||
@@ -176,19 +202,14 @@ if (!isShorthand) { // vue 3.4+ | ||
yield* (0, camelized_1.generateCamelized)(exp.loc.source, exp.loc.start.offset, features); | ||
if (inlayHints) { | ||
yield [ | ||
'', | ||
'template', | ||
exp.loc.end.offset, | ||
{ | ||
__hint: { | ||
setting: 'vue.inlayHints.vBindShorthand', | ||
label: `="${propVariableName}"`, | ||
tooltip: [ | ||
`This is a shorthand for \`${exp.loc.source}="${propVariableName}"\`.`, | ||
'To hide this hint, set `vue.inlayHints.vBindShorthand` to `false` in IDE settings.', | ||
'[More info](https://github.com/vuejs/core/pull/9451)', | ||
].join('\n\n'), | ||
}, | ||
}, | ||
]; | ||
if (enableCodeFeatures) { | ||
ctx.inlayHints.push({ | ||
blockName: 'template', | ||
offset: prop.loc.end.offset, | ||
setting: 'vue.inlayHints.vBindShorthand', | ||
label: `="${propVariableName}"`, | ||
tooltip: [ | ||
`This is a shorthand for \`${prop.loc.source}="${propVariableName}"\`.`, | ||
'To hide this hint, set `vue.inlayHints.vBindShorthand` to `false` in IDE settings.', | ||
'[More info](https://github.com/vuejs/core/pull/9451)', | ||
].join('\n\n'), | ||
}); | ||
} | ||
@@ -195,0 +216,0 @@ } |
@@ -12,7 +12,10 @@ import * as CompilerDOM from '@vue/compiler-dom'; | ||
scriptSetupImportComponentNames: Set<string>; | ||
edited: boolean; | ||
templateRefNames: Map<string, string>; | ||
hasDefineSlots?: boolean; | ||
slotsAssignName?: string; | ||
propsAssignName?: string; | ||
inheritAttrs: boolean; | ||
} | ||
export declare function generateTemplate(options: TemplateCodegenOptions): Generator<Code, TemplateCodegenContext>; | ||
export declare function forEachElementNode(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode): Generator<CompilerDOM.ElementNode>; |
@@ -11,4 +11,5 @@ "use strict"; | ||
const templateChild_1 = require("./templateChild"); | ||
const styleScopedClasses_1 = require("./styleScopedClasses"); | ||
function* generateTemplate(options) { | ||
const ctx = (0, context_1.createTemplateCodegenContext)(options.scriptSetupBindingNames); | ||
const ctx = (0, context_1.createTemplateCodegenContext)(options); | ||
if (options.slotsAssignName) { | ||
@@ -24,3 +25,3 @@ ctx.addLocalVariable(options.slotsAssignName); | ||
} | ||
yield* generateStyleScopedClasses(); | ||
yield* (0, styleScopedClasses_1.generateStyleScopedClasses)(ctx); | ||
if (!options.hasDefineSlots) { | ||
@@ -31,4 +32,16 @@ yield `var __VLS_slots!:`; | ||
} | ||
yield* generateInheritedAttrs(); | ||
yield* ctx.generateAutoImportCompletion(); | ||
yield* generateRefs(); | ||
return ctx; | ||
function* generateRefs() { | ||
for (const [, validId] of options.templateRefNames) { | ||
yield `let ${validId}${common_1.newLine}`; | ||
} | ||
yield `const __VLS_refs = {${common_1.newLine}`; | ||
for (const [name, validId] of options.templateRefNames) { | ||
yield `'${name}': ${validId}!,${common_1.newLine}`; | ||
} | ||
yield `}${common_1.endOfLine}`; | ||
} | ||
function* generateSlotsType() { | ||
@@ -52,43 +65,13 @@ for (const { expVar, varName } of ctx.dynamicSlots) { | ||
} | ||
function* generateStyleScopedClasses() { | ||
yield `if (typeof __VLS_styleScopedClasses === 'object' && !Array.isArray(__VLS_styleScopedClasses)) {${common_1.newLine}`; | ||
for (const offset of ctx.emptyClassOffsets) { | ||
yield `__VLS_styleScopedClasses['`; | ||
yield [ | ||
'', | ||
'template', | ||
offset, | ||
ctx.codeFeatures.additionalCompletion, | ||
]; | ||
yield `']${common_1.endOfLine}`; | ||
function* generateInheritedAttrs() { | ||
yield 'var __VLS_inheritedAttrs!: {}'; | ||
for (const varName of ctx.inheritedAttrVars) { | ||
yield ` & typeof ${varName}`; | ||
} | ||
for (const { className, offset } of ctx.scopedClasses) { | ||
yield `__VLS_styleScopedClasses[`; | ||
yield [ | ||
'', | ||
'template', | ||
offset, | ||
ctx.codeFeatures.navigationWithoutRename, | ||
]; | ||
yield `'`; | ||
yield [ | ||
className, | ||
'template', | ||
offset, | ||
ctx.codeFeatures.navigationAndAdditionalCompletion, | ||
]; | ||
yield `'`; | ||
yield [ | ||
'', | ||
'template', | ||
offset + className.length, | ||
ctx.codeFeatures.navigationWithoutRename, | ||
]; | ||
yield `]${common_1.endOfLine}`; | ||
} | ||
yield `}${common_1.newLine}`; | ||
yield common_1.endOfLine; | ||
} | ||
function* generatePreResolveComponents() { | ||
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)) { | ||
@@ -99,3 +82,8 @@ if (node.tagType === CompilerDOM.ElementTypes.COMPONENT | ||
) { | ||
yield ` & __VLS_WithComponent<'${(0, element_1.getCanonicalComponentName)(node.tag)}', typeof __VLS_localComponents, `; | ||
if (components.has(node.tag)) { | ||
continue; | ||
} | ||
components.add(node.tag); | ||
yield common_1.newLine; | ||
yield ` & __VLS_WithComponent<'${(0, element_1.getCanonicalComponentName)(node.tag)}', typeof __VLS_components, `; | ||
yield (0, element_1.getPossibleOriginalComponentNames)(node.tag, false) | ||
@@ -108,3 +96,3 @@ .map(name => `"${name}"`) | ||
} | ||
yield common_1.endOfLine; | ||
yield `>${common_1.endOfLine}`; | ||
} | ||
@@ -111,0 +99,0 @@ } |
@@ -5,3 +5,3 @@ import type * as ts from 'typescript'; | ||
import type { TemplateCodegenOptions } from './index'; | ||
export declare function generateInterpolation(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, _code: string, astHolder: any, start: number | undefined, data: VueCodeInformation | (() => VueCodeInformation) | undefined, prefix: string, suffix: string): Generator<Code>; | ||
export declare function generateInterpolation(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, _code: string, astHolder: any, start: number | undefined, data: VueCodeInformation | ((offset: number) => VueCodeInformation) | undefined, prefix: string, suffix: string): Generator<Code>; | ||
export declare function forEachInterpolationSegment(ts: typeof import('typescript'), ctx: TemplateCodegenContext, code: string, offset: number | undefined, ast: ts.SourceFile): Generator<[fragment: string, offset: number | undefined, isJustForErrorMapping?: boolean]>; |
@@ -36,3 +36,3 @@ "use strict"; | ||
? ctx.codeFeatures.verification | ||
: typeof data === 'function' ? data() : data, | ||
: typeof data === 'function' ? data(start + offset) : data, | ||
]; | ||
@@ -128,16 +128,3 @@ } | ||
else if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) { | ||
const functionArgs = []; | ||
for (const param of node.parameters) { | ||
(0, common_1.collectVars)(ts, param.name, ast, functionArgs); | ||
if (param.type) { | ||
walkIdentifiers(ts, param.type, ast, cb, ctx, blockVars, false); | ||
} | ||
} | ||
for (const varName of functionArgs) { | ||
ctx.addLocalVariable(varName); | ||
} | ||
walkIdentifiers(ts, node.body, ast, cb, ctx, blockVars, false); | ||
for (const varName of functionArgs) { | ||
ctx.removeLocalVariable(varName); | ||
} | ||
processFunction(ts, node, ast, cb, ctx); | ||
} | ||
@@ -162,2 +149,6 @@ else if (ts.isObjectLiteralExpression(node)) { | ||
} | ||
// fix https://github.com/vuejs/language-tools/issues/4604 | ||
else if (ts.isFunctionLike(prop) && prop.body) { | ||
processFunction(ts, prop, ast, cb, ctx); | ||
} | ||
} | ||
@@ -188,2 +179,20 @@ } | ||
} | ||
function processFunction(ts, node, ast, cb, ctx) { | ||
const functionArgs = []; | ||
for (const param of node.parameters) { | ||
(0, common_1.collectVars)(ts, param.name, ast, functionArgs); | ||
if (param.type) { | ||
walkIdentifiers(ts, param.type, ast, cb, ctx); | ||
} | ||
} | ||
for (const varName of functionArgs) { | ||
ctx.addLocalVariable(varName); | ||
} | ||
if (node.body) { | ||
walkIdentifiers(ts, node.body, ast, cb, ctx); | ||
} | ||
for (const varName of functionArgs) { | ||
ctx.removeLocalVariable(varName); | ||
} | ||
} | ||
function walkIdentifiersInTypeReference(ts, node, cb) { | ||
@@ -190,0 +199,0 @@ if (ts.isTypeQueryNode(node) && ts.isIdentifier(node.exprName)) { |
import type { Code, VueCodeInformation } from '../../types'; | ||
import type { TemplateCodegenContext } from './context'; | ||
import type { TemplateCodegenOptions } from './index'; | ||
export declare function generateObjectProperty(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, code: string, offset: number, features: VueCodeInformation, astHolder?: any, shouldCamelize?: boolean): Generator<Code>; | ||
export declare function generateObjectProperty(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, code: string, offset: number, features: VueCodeInformation, astHolder?: any, shouldCamelize?: boolean, shouldBeConstant?: boolean): Generator<Code>; |
@@ -9,5 +9,10 @@ "use strict"; | ||
const stringLiteralKey_1 = require("./stringLiteralKey"); | ||
function* generateObjectProperty(options, ctx, code, offset, features, astHolder, shouldCamelize = false) { | ||
function* generateObjectProperty(options, ctx, code, offset, features, astHolder, shouldCamelize = false, shouldBeConstant = false) { | ||
if (code.startsWith('[') && code.endsWith(']') && astHolder) { | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, code, astHolder, offset, features, '', ''); | ||
if (shouldBeConstant) { | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, code.slice(1, -1), astHolder, offset + 1, features, `[__VLS_tryAsConstant(`, `)]`); | ||
} | ||
else { | ||
yield* (0, interpolation_1.generateInterpolation)(options, ctx, code, astHolder, offset, features, '', ''); | ||
} | ||
} | ||
@@ -14,0 +19,0 @@ else if (shouldCamelize) { |
@@ -42,4 +42,8 @@ "use strict"; | ||
} | ||
const shouldInheritRootNodeAttrs = options.inheritAttrs; | ||
if (node.type === CompilerDOM.NodeTypes.ROOT) { | ||
let prev; | ||
if (shouldInheritRootNodeAttrs && node.children.length === 1 && node.children[0].type === CompilerDOM.NodeTypes.ELEMENT) { | ||
ctx.singleRootNode = node.children[0]; | ||
} | ||
for (const childNode of node.children) { | ||
@@ -69,3 +73,3 @@ yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar); | ||
else { | ||
yield* (0, element_1.generateComponent)(options, ctx, node, currentComponent, componentCtxVar); | ||
yield* (0, element_1.generateComponent)(options, ctx, node, currentComponent); | ||
} | ||
@@ -72,0 +76,0 @@ } |
@@ -1,8 +0,6 @@ | ||
import { type LanguagePlugin } from '@volar/language-core'; | ||
import { LanguagePlugin } from '@volar/language-core'; | ||
import type * as ts from 'typescript'; | ||
import type { VueCompilerOptions } from './types'; | ||
import { VueVirtualCode } from './virtualFile/vueFile'; | ||
export declare function createRootFileChecker(getProjectVersion: (() => string) | undefined, getRootFileNames: () => string[], caseSensitive: boolean): (fileName: string) => boolean; | ||
export declare function createVueLanguagePlugin<T>(ts: typeof import('typescript'), asFileName: (scriptId: T) => string, _getProjectVersion: (() => string) | undefined, isRootFile: (fileName: string) => boolean, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions): LanguagePlugin<T, VueVirtualCode>; | ||
export declare function createVueLanguagePlugin2<T>(ts: typeof import('typescript'), asFileName: (scriptId: T) => string, isRootFile: (fileName: string) => boolean, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions): LanguagePlugin<T, VueVirtualCode>; | ||
export declare function createVueLanguagePlugin<T>(ts: typeof import('typescript'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, asFileName: (scriptId: T) => string): LanguagePlugin<T, VueVirtualCode>; | ||
export declare function getAllExtensions(options: VueCompilerOptions): string[]; |
"use strict"; | ||
/// <reference types="@volar/typescript" /> | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createRootFileChecker = createRootFileChecker; | ||
exports.createVueLanguagePlugin = createVueLanguagePlugin; | ||
exports.createVueLanguagePlugin2 = createVueLanguagePlugin2; | ||
exports.getAllExtensions = getAllExtensions; | ||
@@ -13,6 +11,4 @@ const language_core_1 = require("@volar/language-core"); | ||
const vueFile_1 = require("./virtualFile/vueFile"); | ||
const normalFileRegistries = []; | ||
const holderFileRegistries = []; | ||
function getVueFileRegistry(isGlobalTypesHolder, key, plugins) { | ||
const fileRegistries = isGlobalTypesHolder ? holderFileRegistries : normalFileRegistries; | ||
const fileRegistries = []; | ||
function getVueFileRegistry(key, plugins) { | ||
let fileRegistry = fileRegistries.find(r => r.key === key | ||
@@ -43,21 +39,3 @@ && r.plugins.length === plugins.length | ||
} | ||
function createRootFileChecker(getProjectVersion, getRootFileNames, caseSensitive) { | ||
const fileNames = new language_core_1.FileMap(caseSensitive); | ||
let projectVersion; | ||
return (fileName) => { | ||
if (!getProjectVersion || projectVersion !== getProjectVersion()) { | ||
projectVersion = getProjectVersion?.(); | ||
fileNames.clear(); | ||
for (const rootFileName of getRootFileNames()) { | ||
fileNames.set(rootFileName, undefined); | ||
} | ||
} | ||
return fileNames.has(fileName); | ||
}; | ||
} | ||
// TODO: replace `createVueLanguagePlugin` with `createVueLanguagePlugin2` in 2.1 | ||
function createVueLanguagePlugin(ts, asFileName, _getProjectVersion, isRootFile, compilerOptions, vueCompilerOptions) { | ||
return createVueLanguagePlugin2(ts, asFileName, isRootFile, compilerOptions, vueCompilerOptions); | ||
} | ||
function createVueLanguagePlugin2(ts, asFileName, isRootFile, compilerOptions, vueCompilerOptions) { | ||
function createVueLanguagePlugin(ts, compilerOptions, vueCompilerOptions, asFileName) { | ||
const pluginContext = { | ||
@@ -75,5 +53,5 @@ modules: { | ||
vueCompilerOptions, | ||
globalTypesHolder: undefined, | ||
}; | ||
const plugins = (0, plugins_1.createPlugins)(pluginContext); | ||
const fileRegistry = getVueFileRegistry(getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins), vueCompilerOptions.plugins); | ||
return { | ||
@@ -92,6 +70,2 @@ getLanguageId(scriptId) { | ||
if (plugins.some(plugin => plugin.isValidFile?.(fileName, languageId))) { | ||
if (!pluginContext.globalTypesHolder && isRootFile(fileName)) { | ||
pluginContext.globalTypesHolder = fileName; | ||
} | ||
const fileRegistry = getFileRegistry(pluginContext.globalTypesHolder === fileName); | ||
const code = fileRegistry.get(fileName); | ||
@@ -113,26 +87,2 @@ if (code) { | ||
}, | ||
// TODO: when global types holder deleted, move global types to another file | ||
// disposeVirtualCode(fileId, code) { | ||
// const isGlobalTypesHolder = code.fileName === pluginContext.globalTypesHolder; | ||
// const fileRegistry = getFileRegistry(isGlobalTypesHolder); | ||
// fileRegistry.delete(fileId); | ||
// if (isGlobalTypesHolder) { | ||
// pluginContext.globalTypesHolder = undefined; | ||
// const fileRegistry2 = getFileRegistry(false); | ||
// for (const [fileId, code] of fileRegistry2) { | ||
// if (isValidGlobalTypesHolder(code.fileName)) { | ||
// pluginContext.globalTypesHolder = code.fileName; | ||
// fileRegistry2.delete(fileId); | ||
// // force dirty | ||
// files?.delete(fileId); | ||
// files?.set( | ||
// fileId, | ||
// code.languageId, | ||
// code.snapshot, | ||
// ); | ||
// break; | ||
// } | ||
// } | ||
// } | ||
// }, | ||
typescript: { | ||
@@ -162,5 +112,2 @@ extraFileExtensions: getAllExtensions(vueCompilerOptions) | ||
}; | ||
function getFileRegistry(isGlobalTypesHolder) { | ||
return getVueFileRegistry(isGlobalTypesHolder, getFileRegistryKey(compilerOptions, vueCompilerOptions, plugins), vueCompilerOptions.plugins); | ||
} | ||
} | ||
@@ -167,0 +114,0 @@ function getAllExtensions(options) { |
@@ -13,2 +13,3 @@ import type { TextRange } from '../types'; | ||
nameOption: TextRange | undefined; | ||
inheritAttrsOption: string | undefined; | ||
}) | undefined; | ||
@@ -15,0 +16,0 @@ classBlockEnd: number | undefined; |
@@ -28,2 +28,3 @@ "use strict"; | ||
let nameOptionNode; | ||
let inheritAttrsOption; | ||
ts.forEachChild(obj, node => { | ||
@@ -38,2 +39,5 @@ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) { | ||
} | ||
if (name === 'inheritAttrs') { | ||
inheritAttrsOption = (0, scriptSetupRanges_1.getNodeText)(ts, node.initializer, ast); | ||
} | ||
} | ||
@@ -49,2 +53,3 @@ }); | ||
nameOption: nameOptionNode ? _getStartEnd(nameOptionNode) : undefined, | ||
inheritAttrsOption, | ||
}; | ||
@@ -51,0 +56,0 @@ } |
@@ -12,2 +12,3 @@ import type * as ts from 'typescript'; | ||
name?: string; | ||
destructured?: string[]; | ||
define?: ReturnType<(node: ts.CallExpression) => TextRange & { | ||
@@ -47,7 +48,16 @@ arg?: TextRange; | ||
}; | ||
options: { | ||
name?: string; | ||
inheritAttrs?: string; | ||
}; | ||
cssModules: { | ||
exp: TextRange; | ||
arg?: TextRange; | ||
}[]; | ||
defineProp: { | ||
localName: TextRange | undefined; | ||
name: TextRange | undefined; | ||
nameIsString: boolean; | ||
type: TextRange | undefined; | ||
modifierType?: TextRange | undefined; | ||
runtimeType: TextRange | undefined; | ||
defaultValue: TextRange | undefined; | ||
@@ -57,5 +67,9 @@ required: boolean; | ||
}[]; | ||
options: { | ||
templateRefs: { | ||
name?: string; | ||
}; | ||
define?: ReturnType<(node: ts.CallExpression) => TextRange & { | ||
arg?: TextRange; | ||
typeArg?: TextRange; | ||
}>; | ||
}[]; | ||
}; | ||
@@ -62,0 +76,0 @@ export declare function parseBindingRanges(ts: typeof import('typescript'), sourceFile: ts.SourceFile): TextRange[]; |
@@ -8,2 +8,3 @@ "use strict"; | ||
exports.getNodeText = getNodeText; | ||
const common_1 = require("../codegen/common"); | ||
function parseScriptSetupRanges(ts, ast, vueCompilerOptions) { | ||
@@ -17,2 +18,4 @@ let foundNonImportExportNode = false; | ||
const options = {}; | ||
const cssModules = []; | ||
const templateRefs = []; | ||
const definePropProposalA = vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition'); | ||
@@ -62,4 +65,6 @@ const definePropProposalB = vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition'); | ||
expose, | ||
options, | ||
cssModules, | ||
defineProp, | ||
options, | ||
templateRefs, | ||
}; | ||
@@ -82,6 +87,11 @@ function _getStartEnd(node) { | ||
if (vueCompilerOptions.macros.defineModel.includes(callText)) { | ||
let name; | ||
let localName; | ||
let propName; | ||
let options; | ||
if (ts.isVariableDeclaration(parent) && | ||
ts.isIdentifier(parent.name)) { | ||
localName = _getStartEnd(parent.name); | ||
} | ||
if (node.arguments.length >= 2) { | ||
name = _getStartEnd(node.arguments[0]); | ||
propName = _getStartEnd(node.arguments[0]); | ||
options = node.arguments[1]; | ||
@@ -91,3 +101,3 @@ } | ||
if (ts.isStringLiteral(node.arguments[0])) { | ||
name = _getStartEnd(node.arguments[0]); | ||
propName = _getStartEnd(node.arguments[0]); | ||
} | ||
@@ -98,8 +108,19 @@ else { | ||
} | ||
let runtimeType; | ||
let defaultValue; | ||
let required = false; | ||
if (options && ts.isObjectLiteralExpression(options)) { | ||
for (const property of options.properties) { | ||
if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && getNodeText(ts, property.name, ast) === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) { | ||
if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) { | ||
continue; | ||
} | ||
const text = getNodeText(ts, property.name, ast); | ||
if (text === 'type') { | ||
runtimeType = _getStartEnd(property.initializer); | ||
} | ||
else if (text === 'default') { | ||
defaultValue = _getStartEnd(property.initializer); | ||
} | ||
else if (text === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) { | ||
required = true; | ||
break; | ||
} | ||
@@ -109,7 +130,8 @@ } | ||
defineProp.push({ | ||
name, | ||
nameIsString: true, | ||
localName, | ||
name: propName, | ||
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined, | ||
modifierType: node.typeArguments && node.typeArguments?.length >= 2 ? _getStartEnd(node.typeArguments[1]) : undefined, | ||
defaultValue: undefined, | ||
runtimeType, | ||
defaultValue, | ||
required, | ||
@@ -120,43 +142,69 @@ isModel: true, | ||
else if (callText === 'defineProp') { | ||
let localName; | ||
let propName; | ||
let options; | ||
if (ts.isVariableDeclaration(parent) && | ||
ts.isIdentifier(parent.name)) { | ||
localName = _getStartEnd(parent.name); | ||
} | ||
let runtimeType; | ||
let defaultValue; | ||
let required = false; | ||
if (definePropProposalA) { | ||
let required = false; | ||
if (node.arguments.length >= 2) { | ||
const secondArg = node.arguments[1]; | ||
if (ts.isObjectLiteralExpression(secondArg)) { | ||
for (const property of secondArg.properties) { | ||
if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && getNodeText(ts, property.name, ast) === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) { | ||
required = true; | ||
break; | ||
} | ||
options = node.arguments[1]; | ||
} | ||
if (node.arguments.length >= 1) { | ||
propName = _getStartEnd(node.arguments[0]); | ||
} | ||
if (options && ts.isObjectLiteralExpression(options)) { | ||
for (const property of options.properties) { | ||
if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) { | ||
continue; | ||
} | ||
const text = getNodeText(ts, property.name, ast); | ||
if (text === 'type') { | ||
runtimeType = _getStartEnd(property.initializer); | ||
} | ||
else if (text === 'default') { | ||
defaultValue = _getStartEnd(property.initializer); | ||
} | ||
else if (text === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) { | ||
required = true; | ||
} | ||
} | ||
} | ||
} | ||
else if (definePropProposalB) { | ||
if (node.arguments.length >= 3) { | ||
options = node.arguments[2]; | ||
} | ||
if (node.arguments.length >= 2) { | ||
if (node.arguments[1].kind === ts.SyntaxKind.TrueKeyword) { | ||
required = true; | ||
} | ||
} | ||
if (node.arguments.length >= 1) { | ||
defineProp.push({ | ||
name: _getStartEnd(node.arguments[0]), | ||
nameIsString: true, | ||
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined, | ||
defaultValue: undefined, | ||
required, | ||
}); | ||
defaultValue = _getStartEnd(node.arguments[0]); | ||
} | ||
else if (ts.isVariableDeclaration(parent)) { | ||
defineProp.push({ | ||
name: _getStartEnd(parent.name), | ||
nameIsString: false, | ||
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined, | ||
defaultValue: undefined, | ||
required, | ||
}); | ||
if (options && ts.isObjectLiteralExpression(options)) { | ||
for (const property of options.properties) { | ||
if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) { | ||
continue; | ||
} | ||
const text = getNodeText(ts, property.name, ast); | ||
if (text === 'type') { | ||
runtimeType = _getStartEnd(property.initializer); | ||
} | ||
} | ||
} | ||
} | ||
else if (definePropProposalB && ts.isVariableDeclaration(parent)) { | ||
defineProp.push({ | ||
name: _getStartEnd(parent.name), | ||
nameIsString: false, | ||
defaultValue: node.arguments.length >= 1 ? _getStartEnd(node.arguments[0]) : undefined, | ||
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined, | ||
required: node.arguments.length >= 2 && node.arguments[1].kind === ts.SyntaxKind.TrueKeyword, | ||
}); | ||
} | ||
defineProp.push({ | ||
localName, | ||
name: propName, | ||
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined, | ||
runtimeType, | ||
defaultValue, | ||
required, | ||
}); | ||
} | ||
@@ -192,2 +240,10 @@ else if (vueCompilerOptions.macros.defineSlots.includes(callText)) { | ||
else if (vueCompilerOptions.macros.defineProps.includes(callText)) { | ||
if (ts.isVariableDeclaration(parent)) { | ||
if (ts.isObjectBindingPattern(parent.name)) { | ||
props.destructured = (0, common_1.collectVars)(ts, parent.name, ast, [], false); | ||
} | ||
else { | ||
props.name = getNodeText(ts, parent.name, ast); | ||
} | ||
} | ||
let statementRange; | ||
@@ -212,5 +268,2 @@ for (let i = parents.length - 1; i >= 0; i--) { | ||
}; | ||
if (ts.isVariableDeclaration(parent)) { | ||
props.name = getNodeText(ts, parent.name, ast); | ||
} | ||
if (node.arguments.length) { | ||
@@ -235,2 +288,11 @@ props.define.arg = _getStartEnd(node.arguments[0]); | ||
if (node.arguments.length && ts.isObjectLiteralExpression(node.arguments[0])) { | ||
const obj = node.arguments[0]; | ||
ts.forEachChild(obj, node => { | ||
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) { | ||
const name = getNodeText(ts, node.name, ast); | ||
if (name === 'inheritAttrs') { | ||
options.inheritAttrs = getNodeText(ts, node.initializer, ast); | ||
} | ||
} | ||
}); | ||
for (const prop of node.arguments[0].properties) { | ||
@@ -243,2 +305,23 @@ if ((ts.isPropertyAssignment(prop)) && getNodeText(ts, prop.name, ast) === 'name' && ts.isStringLiteral(prop.initializer)) { | ||
} | ||
else if (vueCompilerOptions.macros.templateRef.includes(callText) && node.arguments.length && !node.typeArguments?.length) { | ||
const define = parseDefineFunction(node); | ||
define.arg = _getStartEnd(node.arguments[0]); | ||
let name; | ||
if (ts.isVariableDeclaration(parent)) { | ||
name = getNodeText(ts, parent.name, ast); | ||
} | ||
templateRefs.push({ | ||
name, | ||
define | ||
}); | ||
} | ||
else if (vueCompilerOptions.composibles.useCssModule.includes(callText)) { | ||
const module = { | ||
exp: _getStartEnd(node) | ||
}; | ||
if (node.arguments.length) { | ||
module.arg = _getStartEnd(node.arguments[0]); | ||
} | ||
cssModules.push(module); | ||
} | ||
} | ||
@@ -245,0 +328,0 @@ ts.forEachChild(node, child => { |
@@ -21,2 +21,3 @@ "use strict"; | ||
const file_vue_1 = require("./plugins/file-vue"); | ||
const vue_root_tags_1 = require("./plugins/vue-root-tags"); | ||
const vue_script_js_1 = require("./plugins/vue-script-js"); | ||
@@ -38,2 +39,3 @@ const vue_sfc_customblocks_1 = require("./plugins/vue-sfc-customblocks"); | ||
file_html_1.default, | ||
vue_root_tags_1.default, | ||
vue_script_js_1.default, | ||
@@ -40,0 +42,0 @@ vue_template_html_1.default, |
@@ -75,10 +75,13 @@ "use strict"; | ||
function transformRange(block) { | ||
block.loc.start.offset = -1; | ||
block.loc.end.offset = -1; | ||
for (const [start] of file2VueSourceMap.toSourceLocation(block.loc.start.offset)) { | ||
block.loc.start.offset = start; | ||
const { start, end } = block.loc; | ||
const startOffset = start.offset; | ||
const endOffset = end.offset; | ||
start.offset = -1; | ||
end.offset = -1; | ||
for (const [offset] of file2VueSourceMap.toSourceLocation(startOffset)) { | ||
start.offset = offset; | ||
break; | ||
} | ||
for (const [end] of file2VueSourceMap.toSourceLocation(block.loc.end.offset)) { | ||
block.loc.end.offset = end; | ||
for (const [offset] of file2VueSourceMap.toSourceLocation(endOffset)) { | ||
end.offset = offset; | ||
break; | ||
@@ -85,0 +88,0 @@ } |
@@ -12,2 +12,3 @@ import type { Mapping } from '@volar/language-core'; | ||
nameOption: import("../types").TextRange | undefined; | ||
inheritAttrsOption: string | undefined; | ||
}) | undefined; | ||
@@ -24,2 +25,3 @@ classBlockEnd: number | undefined; | ||
name?: string; | ||
destructured?: string[]; | ||
define?: ReturnType<(node: import("typescript").CallExpression) => import("../types").TextRange & { | ||
@@ -59,7 +61,16 @@ arg?: import("../types").TextRange; | ||
}; | ||
options: { | ||
name?: string; | ||
inheritAttrs?: string; | ||
}; | ||
cssModules: { | ||
exp: import("../types").TextRange; | ||
arg?: import("../types").TextRange; | ||
}[]; | ||
defineProp: { | ||
localName: import("../types").TextRange | undefined; | ||
name: import("../types").TextRange | undefined; | ||
nameIsString: boolean; | ||
type: import("../types").TextRange | undefined; | ||
modifierType?: import("../types").TextRange | undefined; | ||
runtimeType: import("../types").TextRange | undefined; | ||
defaultValue: import("../types").TextRange | undefined; | ||
@@ -69,5 +80,9 @@ required: boolean; | ||
}[]; | ||
options: { | ||
templateRefs: { | ||
name?: string; | ||
}; | ||
define?: ReturnType<(node: import("typescript").CallExpression) => import("../types").TextRange & { | ||
arg?: import("../types").TextRange; | ||
typeArg?: import("../types").TextRange; | ||
}>; | ||
}[]; | ||
} | undefined; | ||
@@ -78,2 +93,20 @@ lang: () => string; | ||
linkedCodeMappings: Mapping<unknown>[]; | ||
generatedTemplate: boolean; | ||
generatedPropsType: boolean; | ||
scriptSetupGeneratedOffset: number | undefined; | ||
bypassDefineComponent: boolean; | ||
bindingNames: Set<string>; | ||
localTypes: { | ||
generate: (names: string[]) => Generator<string, void, unknown>; | ||
getUsedNames(): Set<string>; | ||
readonly PrettifyLocal: string; | ||
readonly OmitKeepDiscriminatedUnion: string; | ||
readonly WithDefaults: string; | ||
readonly WithTemplateSlots: string; | ||
readonly PropsChildren: string; | ||
readonly TypePropsToOption: string; | ||
readonly OmitIndexSignature: string; | ||
readonly PickRefsExpose: string; | ||
}; | ||
inlayHints: import("../codegen/types").InlayHintInfo[]; | ||
}; | ||
@@ -111,2 +144,3 @@ generatedTemplate: () => { | ||
scopedClasses: { | ||
source: string; | ||
className: string; | ||
@@ -116,3 +150,6 @@ offset: number; | ||
emptyClassOffsets: number[]; | ||
inlayHints: import("../codegen/types").InlayHintInfo[]; | ||
hasSlot: boolean; | ||
inheritedAttrVars: Set<unknown>; | ||
singleRootNode: import("@vue/compiler-dom").ElementNode | undefined; | ||
accessExternalVariable(name: string, offset?: number): void; | ||
@@ -119,0 +156,0 @@ hasLocalVariable: (name: string) => boolean; |
@@ -11,2 +11,3 @@ "use strict"; | ||
exports.tsCodegen = new WeakMap(); | ||
const fileEditTimes = new Map(); | ||
const plugin = ctx => { | ||
@@ -71,7 +72,10 @@ return { | ||
template: _sfc.template, | ||
edited: ctx.vueCompilerOptions.__test || (fileEditTimes.get(fileName) ?? 0) >= 2, | ||
scriptSetupBindingNames: scriptSetupBindingNames(), | ||
scriptSetupImportComponentNames: scriptSetupImportComponentNames(), | ||
templateRefNames: new Map(), | ||
hasDefineSlots: hasDefineSlots(), | ||
slotsAssignName: slotsAssignName(), | ||
propsAssignName: propsAssignName(), | ||
inheritAttrs: inheritAttrs(), | ||
}); | ||
@@ -112,2 +116,6 @@ let current = codegen.next(); | ||
const propsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.props.name); | ||
const inheritAttrs = (0, computeds_1.computed)(() => { | ||
const value = scriptSetupRanges()?.options.inheritAttrs ?? scriptRanges()?.exportDefault?.inheritAttrsOption; | ||
return value !== 'false'; | ||
}); | ||
const generatedScript = (0, computeds_1.computed)(() => { | ||
@@ -118,6 +126,5 @@ const codes = []; | ||
let generatedLength = 0; | ||
for (const code of (0, script_1.generateScript)({ | ||
const codegen = (0, script_1.generateScript)({ | ||
ts, | ||
fileBaseName: path.basename(fileName), | ||
globalTypes: ctx.globalTypesHolder === fileName, | ||
sfc: _sfc, | ||
@@ -130,5 +137,10 @@ lang: lang(), | ||
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(); | ||
while (!current.done) { | ||
const code = current.value; | ||
codes.push(code); | ||
@@ -138,5 +150,6 @@ generatedLength += typeof code === 'string' | ||
: code[0].length; | ||
current = codegen.next(); | ||
} | ||
; | ||
return { | ||
...current.value, | ||
codes, | ||
@@ -143,0 +156,0 @@ linkedCodeMappings, |
@@ -14,9 +14,2 @@ import type { CodeInformation } from '@volar/language-core'; | ||
export interface VueCodeInformation extends CodeInformation { | ||
__hint?: { | ||
setting: string; | ||
label: string; | ||
tooltip: string; | ||
paddingRight?: boolean; | ||
paddingLeft?: boolean; | ||
}; | ||
__combineLastMapping?: boolean; | ||
@@ -35,2 +28,3 @@ __combineOffsetMapping?: number; | ||
skipTemplateCodegen: boolean; | ||
fallthroughAttributes: boolean; | ||
dataAttributes: string[]; | ||
@@ -47,3 +41,7 @@ htmlAttributes: string[]; | ||
withDefaults: string[]; | ||
templateRef: string[]; | ||
}; | ||
composibles: { | ||
useCssModule: string[]; | ||
}; | ||
plugins: VueLanguagePlugin[]; | ||
@@ -53,2 +51,3 @@ experimentalDefinePropProposal: 'kevinEdition' | 'johnsonEdition' | false; | ||
experimentalModelPropName: Record<string, Record<string, boolean | Record<string, string> | Record<string, string>[]>>; | ||
__test?: boolean; | ||
} | ||
@@ -91,3 +90,2 @@ export declare const validVersions: readonly [2, 2.1]; | ||
vueCompilerOptions: VueCompilerOptions; | ||
globalTypesHolder: string | undefined; | ||
}) => VueLanguagePluginReturn | VueLanguagePluginReturn[]; | ||
@@ -104,3 +102,10 @@ export interface SfcBlock { | ||
} | ||
export interface SFCStyleOverride { | ||
module?: { | ||
name: string; | ||
offset?: number; | ||
}; | ||
} | ||
export interface Sfc { | ||
content: string; | ||
template: SfcBlock & { | ||
@@ -121,4 +126,3 @@ ast: CompilerDOM.RootNode | undefined; | ||
} | undefined; | ||
styles: readonly (SfcBlock & { | ||
module: string | undefined; | ||
styles: readonly (SfcBlock & SFCStyleOverride & { | ||
scoped: boolean; | ||
@@ -125,0 +129,0 @@ cssVars: { |
@@ -5,3 +5,3 @@ "use strict"; | ||
const parseCssVars_1 = require("./parseCssVars"); | ||
const cssClassNameReg = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\,\+\{\>#\:]{1})/g; | ||
const cssClassNameReg = /(?=(\.[a-z_][-\w]*)[\s.,+~>:#[{])/gi; | ||
function* parseCssClassNames(styleContent) { | ||
@@ -11,7 +11,5 @@ styleContent = (0, parseCssVars_1.clearComments)(styleContent); | ||
for (const match of matches) { | ||
if (match.index !== undefined) { | ||
const matchText = match[1]; | ||
if (matchText !== undefined) { | ||
yield { offset: match.index, text: matchText }; | ||
} | ||
const matchText = match[1]; | ||
if (matchText) { | ||
yield { offset: match.index, text: matchText }; | ||
} | ||
@@ -18,0 +16,0 @@ } |
@@ -6,3 +6,3 @@ "use strict"; | ||
exports.clearComments = clearComments; | ||
const vBindCssVarReg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g; | ||
const vBindCssVarReg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([a-z_]\w*))\s*\)/gi; | ||
const commentReg1 = /\/\*([\s\S]*?)\*\//g; | ||
@@ -14,8 +14,6 @@ const commentReg2 = /\/\/([\s\S]*?)\n/g; | ||
for (const match of matchs) { | ||
if (match.index !== undefined) { | ||
const matchText = match[1] ?? match[2] ?? match[3]; | ||
if (matchText !== undefined) { | ||
const offset = match.index + styleContent.slice(match.index).indexOf(matchText); | ||
yield { offset, text: matchText }; | ||
} | ||
const matchText = match.slice(1).find(t => t); | ||
if (matchText) { | ||
const offset = match.index + styleContent.slice(match.index).indexOf(matchText); | ||
yield { offset, text: matchText }; | ||
} | ||
@@ -22,0 +20,0 @@ } |
@@ -110,3 +110,6 @@ "use strict"; | ||
else if (p.name === 'module') { | ||
block.module = attrs[p.name]; | ||
block.module = { | ||
name: p.value?.content ?? '$style', | ||
offset: p.value?.content ? p.value?.loc.start.offset - node.loc.start.offset : undefined | ||
}; | ||
} | ||
@@ -113,0 +116,0 @@ } |
@@ -6,2 +6,3 @@ "use strict"; | ||
exports.resolveVueCompilerOptions = resolveVueCompilerOptions; | ||
const shared_1 = require("@vue/shared"); | ||
const path = require("path-browserify"); | ||
@@ -170,2 +171,3 @@ const languagePlugin_1 = require("../languagePlugin"); | ||
skipTemplateCodegen: vueOptions.skipTemplateCodegen ?? false, | ||
fallthroughAttributes: vueOptions.fallthroughAttributes ?? false, | ||
dataAttributes: vueOptions.dataAttributes ?? [], | ||
@@ -184,4 +186,8 @@ htmlAttributes: vueOptions.htmlAttributes ?? ['aria-*'], | ||
withDefaults: ['withDefaults'], | ||
templateRef: ['templateRef', 'useTemplateRef'], | ||
...vueOptions.macros, | ||
}, | ||
composibles: { | ||
useCssModule: ['useCssModule'] | ||
}, | ||
plugins: vueOptions.plugins ?? [], | ||
@@ -193,3 +199,3 @@ // experimental | ||
// https://vuejs.org/guide/essentials/forms.html#form-input-bindings | ||
experimentalModelPropName: vueOptions.experimentalModelPropName ?? { | ||
experimentalModelPropName: Object.fromEntries(Object.entries(vueOptions.experimentalModelPropName ?? { | ||
'': { | ||
@@ -203,5 +209,5 @@ input: true | ||
} | ||
}, | ||
}).map(([k, v]) => [(0, shared_1.camelize)(k), v])), | ||
}; | ||
} | ||
//# sourceMappingURL=ts.js.map |
import type { SFCParseResult } from '@vue/compiler-sfc'; | ||
import type * as ts from 'typescript'; | ||
import type { Sfc, VueLanguagePluginReturn } from '../types'; | ||
export declare function computedSfc(ts: typeof import('typescript'), plugins: VueLanguagePluginReturn[], fileName: string, snapshot: () => ts.IScriptSnapshot, parsed: () => SFCParseResult | undefined): Sfc; | ||
export declare function computedSfc(ts: typeof import('typescript'), plugins: VueLanguagePluginReturn[], fileName: string, getSnapshot: () => ts.IScriptSnapshot, parsed: () => SFCParseResult | undefined): Sfc; |
@@ -7,9 +7,13 @@ "use strict"; | ||
const parseCssVars_1 = require("../utils/parseCssVars"); | ||
function computedSfc(ts, plugins, fileName, snapshot, parsed) { | ||
function computedSfc(ts, plugins, fileName, getSnapshot, parsed) { | ||
const untrackedSnapshot = () => { | ||
(0, computeds_1.pauseTracking)(); | ||
const res = snapshot(); | ||
const res = getSnapshot(); | ||
(0, computeds_1.resetTracking)(); | ||
return res; | ||
}; | ||
const content = (0, computeds_1.computed)(() => { | ||
const snapshot = getSnapshot(); | ||
return snapshot.getText(0, snapshot.getLength()); | ||
}); | ||
const template = computedNullableSfcBlock('template', 'html', (0, computeds_1.computed)(() => parsed()?.descriptor.template ?? undefined), (_block, base) => { | ||
@@ -91,3 +95,9 @@ const compiledAst = computedTemplateAst(base); | ||
const base = computedSfcBlock('style_' + i, 'css', block); | ||
const module = (0, computeds_1.computed)(() => typeof block().module === 'string' ? block().module : block().module ? '$style' : undefined); | ||
const module = (0, computeds_1.computed)(() => { | ||
const _module = block().module; | ||
return _module ? { | ||
name: _module.name, | ||
offset: _module.offset ? base.start + _module.offset : undefined | ||
} : undefined; | ||
}); | ||
const scoped = (0, computeds_1.computed)(() => !!block().scoped); | ||
@@ -111,2 +121,3 @@ const cssVars = (0, computeds_1.computed)(() => [...(0, parseCssVars_1.parseCssVars)(base.content)]); | ||
return { | ||
get content() { return content(); }, | ||
get template() { return template(); }, | ||
@@ -113,0 +124,0 @@ get script() { return script(); }, |
@@ -13,12 +13,22 @@ import type { VirtualCode } from '@volar/language-core'; | ||
id: string; | ||
_snapshot: Signal<ts.IScriptSnapshot>; | ||
getSnapshot: Signal<ts.IScriptSnapshot>; | ||
getVueSfc: () => import("@vue/compiler-sfc").SFCParseResult | undefined; | ||
sfc: import("../types").Sfc; | ||
getMappings: () => import("@volar/language-core").CodeMapping[]; | ||
getMappings: () => { | ||
sourceOffsets: number[]; | ||
generatedOffsets: number[]; | ||
lengths: number[]; | ||
data: import("@volar/language-core").CodeInformation; | ||
}[]; | ||
getEmbeddedCodes: () => VirtualCode[]; | ||
get embeddedCodes(): VirtualCode[]; | ||
get snapshot(): ts.IScriptSnapshot; | ||
get mappings(): import("@volar/language-core").CodeMapping[]; | ||
get mappings(): { | ||
sourceOffsets: number[]; | ||
generatedOffsets: number[]; | ||
lengths: number[]; | ||
data: import("@volar/language-core").CodeInformation; | ||
}[]; | ||
constructor(fileName: string, languageId: string, initSnapshot: ts.IScriptSnapshot, vueCompilerOptions: VueCompilerOptions, plugins: VueLanguagePluginReturn[], ts: typeof import('typescript')); | ||
update(newSnapshot: ts.IScriptSnapshot): void; | ||
} |
@@ -5,6 +5,6 @@ "use strict"; | ||
const computeds_1 = require("computeds"); | ||
const computedFiles_1 = require("./computedFiles"); | ||
const computedMappings_1 = require("./computedMappings"); | ||
const computedEmbeddedCodes_1 = require("./computedEmbeddedCodes"); | ||
const computedSfc_1 = require("./computedSfc"); | ||
const computedVueSfc_1 = require("./computedVueSfc"); | ||
const plugins_1 = require("../plugins"); | ||
class VueVirtualCode { | ||
@@ -16,3 +16,3 @@ // others | ||
get snapshot() { | ||
return this._snapshot(); | ||
return this.getSnapshot(); | ||
} | ||
@@ -32,10 +32,18 @@ get mappings() { | ||
// computeds | ||
this.getVueSfc = (0, computedVueSfc_1.computedVueSfc)(this.plugins, this.fileName, this.languageId, () => this._snapshot()); | ||
this.sfc = (0, computedSfc_1.computedSfc)(this.ts, this.plugins, this.fileName, () => this._snapshot(), this.getVueSfc); | ||
this.getMappings = (0, computedMappings_1.computedMappings)(() => this._snapshot(), this.sfc); | ||
this.getEmbeddedCodes = (0, computedFiles_1.computedFiles)(this.plugins, this.fileName, this.sfc); | ||
this._snapshot = (0, computeds_1.signal)(initSnapshot); | ||
this.getVueSfc = (0, computedVueSfc_1.computedVueSfc)(this.plugins, this.fileName, this.languageId, () => this.getSnapshot()); | ||
this.sfc = (0, computedSfc_1.computedSfc)(this.ts, this.plugins, this.fileName, () => this.getSnapshot(), this.getVueSfc); | ||
this.getMappings = (0, computeds_1.computed)(() => { | ||
const snapshot = this.getSnapshot(); | ||
return [{ | ||
sourceOffsets: [0], | ||
generatedOffsets: [0], | ||
lengths: [snapshot.getLength()], | ||
data: plugins_1.allCodeFeatures, | ||
}]; | ||
}); | ||
this.getEmbeddedCodes = (0, computedEmbeddedCodes_1.computedEmbeddedCodes)(this.plugins, this.fileName, this.sfc); | ||
this.getSnapshot = (0, computeds_1.signal)(initSnapshot); | ||
} | ||
update(newSnapshot) { | ||
this._snapshot.set(newSnapshot); | ||
this.getSnapshot.set(newSnapshot); | ||
} | ||
@@ -42,0 +50,0 @@ } |
{ | ||
"name": "@vue/language-core", | ||
"version": "2.0.29", | ||
"version": "2.1.0", | ||
"license": "MIT", | ||
@@ -15,3 +15,3 @@ "files": [ | ||
"dependencies": { | ||
"@volar/language-core": "~2.4.0-alpha.18", | ||
"@volar/language-core": "~2.4.1", | ||
"@vue/compiler-dom": "^3.4.0", | ||
@@ -29,3 +29,3 @@ "@vue/compiler-vue2": "^2.7.16", | ||
"@types/path-browserify": "^1.0.1", | ||
"@volar/typescript": "~2.4.0-alpha.18", | ||
"@volar/typescript": "~2.4.1", | ||
"@vue/compiler-sfc": "^3.4.0" | ||
@@ -41,3 +41,3 @@ }, | ||
}, | ||
"gitHead": "49ad9563e6f2677595878a000179dfea83fb910c" | ||
"gitHead": "510063740b90b64caedaee1f0bde70974613a92c" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
320715
124
7196
Updated@volar/language-core@~2.4.1