@vue/language-core
Advanced tools
Comparing version 2.0.16 to 2.0.17
@@ -7,4 +7,3 @@ "use strict"; | ||
const fnPropsType = `(K extends { $props: infer Props } ? Props : any)${vueCompilerOptions.strictTemplates ? '' : ' & Record<string, unknown>'}`; | ||
return ` | ||
; export const __VLS_globalTypesStart = {}; | ||
return `export const __VLS_globalTypesStart = {}; | ||
declare global { | ||
@@ -132,3 +131,4 @@ // @ts-ignore | ||
} | ||
export const __VLS_globalTypesEnd = {};`; | ||
export const __VLS_globalTypesEnd = {}; | ||
`; | ||
} | ||
@@ -135,0 +135,0 @@ exports.generateGlobalTypes = generateGlobalTypes; |
@@ -12,4 +12,3 @@ import type { Mapping } from '@volar/language-core'; | ||
navigation: VueCodeInformation; | ||
referencesCodeLens: VueCodeInformation; | ||
cssClassNavigation: VueCodeInformation; | ||
navigationWithoutRename: VueCodeInformation; | ||
}; | ||
@@ -25,6 +24,4 @@ export interface ScriptCodegenOptions { | ||
scriptSetupRanges: ScriptSetupRanges | undefined; | ||
templateCodegen: { | ||
tsCodes: Code[]; | ||
ctx: TemplateCodegenContext; | ||
hasSlot: boolean; | ||
templateCodegen: TemplateCodegenContext & { | ||
codes: Code[]; | ||
} | undefined; | ||
@@ -31,0 +28,0 @@ globalTypes: boolean; |
@@ -24,10 +24,7 @@ "use strict"; | ||
}, | ||
referencesCodeLens: { | ||
navigation: true, | ||
__referencesCodeLens: true, | ||
}, | ||
cssClassNavigation: { | ||
navigationWithoutRename: { | ||
navigation: { | ||
resolveRenameNewName: normalizeCssRename, | ||
resolveRenameEditText: applyCssRename, | ||
shouldRename() { | ||
return false; | ||
}, | ||
}, | ||
@@ -43,3 +40,3 @@ }, | ||
if (options.sfc.script && options.scriptRanges) { | ||
const { exportDefault } = options.scriptRanges; | ||
const { exportDefault, classBlockEnd } = options.scriptRanges; | ||
const isExportRawObject = exportDefault | ||
@@ -97,2 +94,7 @@ && options.sfc.script.content[exportDefault.expression.start] === '{'; | ||
} | ||
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); | ||
} | ||
else { | ||
@@ -106,2 +108,3 @@ yield (0, common_1.generateSfcBlockSection)(options.sfc.script, 0, options.sfc.script.content.length, exports.codeFeatures.all); | ||
} | ||
yield common_1.endOfLine; | ||
if (options.globalTypes) { | ||
@@ -113,3 +116,3 @@ yield (0, globalTypes_1.generateGlobalTypes)(options.vueCompilerOptions); | ||
if (!ctx.generatedTemplate) { | ||
yield* (0, template_1.generateTemplate)(options, ctx); | ||
yield* (0, template_1.generateTemplate)(options, ctx, false); | ||
} | ||
@@ -126,8 +129,2 @@ if (options.sfc.scriptSetup) { | ||
exports.generateScript = generateScript; | ||
function normalizeCssRename(newName) { | ||
return newName.startsWith('.') ? newName.slice(1) : newName; | ||
} | ||
function applyCssRename(newName) { | ||
return '.' + newName; | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -25,3 +25,3 @@ "use strict"; | ||
const varName = content.substring(expose.start, expose.end); | ||
if (!templateUsageVars.has(varName) && !templateCodegenCtx.accessGlobalVariables.has(varName)) { | ||
if (!templateUsageVars.has(varName) && !templateCodegenCtx.accessExternalVariables.has(varName)) { | ||
continue; | ||
@@ -28,0 +28,0 @@ } |
@@ -39,2 +39,6 @@ "use strict"; | ||
yield* generateSetupFunction(options, ctx, scriptSetup, scriptSetupRanges, undefined, definePropMirrors); | ||
const emitTypes = ['typeof __VLS_modelEmitsType']; | ||
if (scriptSetupRanges.emits.define) { | ||
emitTypes.unshift(`typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'}`); | ||
} | ||
yield ` return {} as {${common_1.newLine}` | ||
@@ -45,3 +49,3 @@ + ` props: ${ctx.helperTypes.Prettify.name}<typeof __VLS_functionalComponentProps & __VLS_PublicProps> & __VLS_BuiltInPublicProps,${common_1.newLine}` | ||
+ ` slots: ReturnType<typeof __VLS_template>,${common_1.newLine}` | ||
+ ` emit: typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'} & typeof __VLS_modelEmitsType,${common_1.newLine}` | ||
+ ` emit: ${emitTypes.join(' & ')},${common_1.newLine}` | ||
+ ` }${common_1.endOfLine}`; | ||
@@ -220,3 +224,3 @@ yield ` })(),${common_1.newLine}`; // __VLS_setup = (async () => { | ||
yield* generateModelEmits(options, scriptSetup, scriptSetupRanges); | ||
yield* (0, template_1.generateTemplate)(options, ctx); | ||
yield* (0, template_1.generateTemplate)(options, ctx, false); | ||
if (syntax) { | ||
@@ -238,23 +242,21 @@ if (!options.vueCompilerOptions.skipTemplateCodegen && (options.templateCodegen?.hasSlot || scriptSetupRanges?.slots.define)) { | ||
function* generateComponentProps(options, ctx, scriptSetup, scriptSetupRanges, definePropMirrors) { | ||
if (scriptSetupRanges.props.define?.arg || scriptSetupRanges.emits.define) { | ||
yield `const __VLS_fnComponent = ` | ||
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${common_1.newLine}`; | ||
if (scriptSetupRanges.props.define?.arg) { | ||
yield ` props: `; | ||
yield (0, common_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, index_1.codeFeatures.navigation); | ||
yield `,${common_1.newLine}`; | ||
} | ||
yield `const __VLS_fnComponent = ` | ||
+ `(await import('${options.vueCompilerOptions.lib}')).defineComponent({${common_1.newLine}`; | ||
if (scriptSetupRanges.props.define?.arg) { | ||
yield ` props: `; | ||
yield (0, common_1.generateSfcBlockSection)(scriptSetup, scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end, index_1.codeFeatures.navigation); | ||
yield `,${common_1.newLine}`; | ||
} | ||
if (scriptSetupRanges.emits.define || scriptSetupRanges.defineProp.some(p => p.isModel)) { | ||
yield ` emits: ({} as __VLS_NormalizeEmits<typeof __VLS_modelEmitsType`; | ||
if (scriptSetupRanges.emits.define) { | ||
yield ` emits: ({} as __VLS_NormalizeEmits<typeof `; | ||
yield ` & typeof `; | ||
yield scriptSetupRanges.emits.name ?? '__VLS_emit'; | ||
yield `>),${common_1.newLine}`; | ||
} | ||
yield `})${common_1.endOfLine}`; | ||
yield `let __VLS_functionalComponentProps!: `; | ||
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`; | ||
yield common_1.endOfLine; | ||
yield `>),${common_1.newLine}`; | ||
} | ||
else { | ||
yield `let __VLS_functionalComponentProps!: {}${common_1.endOfLine}`; | ||
} | ||
yield `})${common_1.endOfLine}`; | ||
yield `let __VLS_functionalComponentProps!: `; | ||
yield `${ctx.helperTypes.OmitKeepDiscriminatedUnion.name}<InstanceType<typeof __VLS_fnComponent>['$props'], keyof __VLS_BuiltInPublicProps>`; | ||
yield common_1.endOfLine; | ||
yield `type __VLS_BuiltInPublicProps =${common_1.newLine}` | ||
@@ -261,0 +263,0 @@ + ` import('${options.vueCompilerOptions.lib}').VNodeProps${common_1.newLine}` |
import type { Code } from '../../types'; | ||
import type { ScriptCodegenContext } from './context'; | ||
import { type ScriptCodegenOptions } from './index'; | ||
export declare function generateTemplate(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Generator<Code>; | ||
export declare function generateTemplate(options: ScriptCodegenOptions, ctx: ScriptCodegenContext, isClassComponent: boolean): Generator<Code>; | ||
export declare function getTemplateUsageVars(options: ScriptCodegenOptions, ctx: ScriptCodegenContext): Set<string>; |
@@ -10,13 +10,18 @@ "use strict"; | ||
const internalComponent_1 = require("./internalComponent"); | ||
const common_2 = require("../common"); | ||
function* generateTemplate(options, ctx) { | ||
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 `function __VLS_template() {${common_1.newLine}`; | ||
const templateCodegenCtx = (0, context_1.createTemplateCodegenContext)(); | ||
yield* generateTemplateContext(options, ctx, templateCodegenCtx); | ||
yield* (0, internalComponent_1.generateInternalComponent)(options, ctx, templateCodegenCtx); | ||
yield `}${common_1.newLine}`; | ||
yield* (0, internalComponent_1.generateInternalComponent)(options, ctx, templateCodegenCtx); | ||
} | ||
@@ -51,3 +56,2 @@ else { | ||
function* generateConstNameOption(options) { | ||
yield common_1.newLine; | ||
if (options.sfc.script && options.scriptRanges?.exportDefault?.nameOption) { | ||
@@ -60,3 +64,3 @@ const nameOption = options.scriptRanges.exportDefault.nameOption; | ||
else if (options.sfc.scriptSetup) { | ||
yield `let __VLS_name!: '${options.fileBaseName.substring(0, options.fileBaseName.lastIndexOf('.'))}'${common_1.endOfLine}`; | ||
yield `let __VLS_name!: '${options.scriptSetupRanges?.options.name ?? options.fileBaseName.substring(0, options.fileBaseName.lastIndexOf('.'))}'${common_1.endOfLine}`; | ||
} | ||
@@ -67,18 +71,31 @@ else { | ||
} | ||
function* generateTemplateContext(options, ctx, templateCodegenCtx) { | ||
const useGlobalThisTypeInCtx = options.fileBaseName.endsWith('.html'); | ||
yield `let __VLS_ctx!: ${useGlobalThisTypeInCtx ? 'typeof globalThis &' : ''}`; | ||
yield `InstanceType<__VLS_PickNotAny<typeof __VLS_internalComponent, new () => {}>> & {${common_1.newLine}`; | ||
function* generateCtx(options, ctx, isClassComponent) { | ||
yield `let __VLS_ctx!: `; | ||
if (options.vueCompilerOptions.petiteVueExtensions.some(ext => options.fileBaseName.endsWith(ext))) { | ||
yield `typeof globalThis & `; | ||
} | ||
if (!isClassComponent) { | ||
yield `InstanceType<__VLS_PickNotAny<typeof __VLS_internalComponent, new () => {}>>`; | ||
} | ||
else { | ||
yield `typeof this`; | ||
} | ||
/* CSS Module */ | ||
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, true); | ||
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 `>${common_1.endOfLine}`; | ||
} | ||
yield `}`; | ||
} | ||
yield `}${common_1.endOfLine}`; | ||
yield common_1.endOfLine; | ||
} | ||
function* generateTemplateContext(options, templateCodegenCtx) { | ||
/* Components */ | ||
@@ -98,3 +115,3 @@ yield `/* Components */${common_1.newLine}`; | ||
for (const className of style.classNames) { | ||
yield* generateCssClassProperty(i, className.text, className.offset, 'boolean', true, !style.module); | ||
yield* generateCssClassProperty(i, className.text, className.offset, 'boolean', true); | ||
} | ||
@@ -107,3 +124,3 @@ } | ||
if (options.templateCodegen) { | ||
for (const code of options.templateCodegen.tsCodes) { | ||
for (const code of options.templateCodegen.codes) { | ||
yield code; | ||
@@ -120,3 +137,3 @@ } | ||
} | ||
function* generateCssClassProperty(styleIndex, classNameWithDot, offset, propertyType, optional, referencesCodeLens) { | ||
function* generateCssClassProperty(styleIndex, classNameWithDot, offset, propertyType, optional) { | ||
yield `${common_1.newLine} & { `; | ||
@@ -127,18 +144,10 @@ yield [ | ||
offset, | ||
referencesCodeLens | ||
? index_1.codeFeatures.navigation | ||
: index_1.codeFeatures.referencesCodeLens, | ||
index_1.codeFeatures.navigationWithoutRename, | ||
]; | ||
yield `'`; | ||
yield [ | ||
'', | ||
'style_' + styleIndex, | ||
offset, | ||
index_1.codeFeatures.cssClassNavigation, | ||
]; | ||
yield [ | ||
classNameWithDot.substring(1), | ||
'style_' + styleIndex, | ||
offset + 1, | ||
common_2.combineLastMapping, | ||
index_1.codeFeatures.navigation, | ||
]; | ||
@@ -150,3 +159,3 @@ yield `'`; | ||
offset + classNameWithDot.length, | ||
index_1.codeFeatures.none, | ||
index_1.codeFeatures.navigationWithoutRename, | ||
]; | ||
@@ -163,3 +172,3 @@ yield `${optional ? '?' : ''}: ${propertyType}`; | ||
for (const cssBind of style.cssVars) { | ||
for (const [segment, offset, onlyError] of (0, interpolation_1.forEachInterpolationSegment)(options.ts, options.vueCompilerOptions, ctx, cssBind.text, cssBind.offset, options.ts.createSourceFile('/a.txt', cssBind.text, 99))) { | ||
for (const [segment, offset, onlyError] of (0, interpolation_1.forEachInterpolationSegment)(options.ts, ctx, cssBind.text, cssBind.offset, options.ts.createSourceFile('/a.txt', cssBind.text, 99))) { | ||
if (offset === undefined) { | ||
@@ -199,3 +208,3 @@ yield segment; | ||
} | ||
for (const [varName] of options.templateCodegen.ctx.accessGlobalVariables) { | ||
for (const [varName] of options.templateCodegen.accessExternalVariables) { | ||
usageVars.add(varName); | ||
@@ -202,0 +211,0 @@ } |
import type * as CompilerDOM from '@vue/compiler-dom'; | ||
import type { Code, VueCodeInformation } from '../../types'; | ||
import type { TemplateCodegenOptions } from './index'; | ||
export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>; | ||
export declare function createTemplateCodegenContext(): { | ||
export declare function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCodegenOptions['scriptSetupBindingNames']): { | ||
slots: { | ||
@@ -22,3 +23,5 @@ name: string; | ||
navigation: VueCodeInformation; | ||
navigationWithoutRename: VueCodeInformation; | ||
navigationAndCompletion: VueCodeInformation; | ||
navigationAndAdditionalCompletion: VueCodeInformation; | ||
withoutHighlight: VueCodeInformation; | ||
@@ -28,3 +31,3 @@ withoutHighlightAndCompletion: VueCodeInformation; | ||
}; | ||
accessGlobalVariables: Map<string, Set<number>>; | ||
accessExternalVariables: Map<string, Set<number>>; | ||
hasSlotElements: Set<CompilerDOM.ElementNode>; | ||
@@ -37,3 +40,5 @@ blockConditions: string[]; | ||
}[]; | ||
accessGlobalVariable(name: string, offset?: number): void; | ||
emptyClassOffsets: number[]; | ||
hasSlot: boolean; | ||
accessExternalVariable(name: string, offset?: number): void; | ||
hasLocalVariable: (name: string) => boolean; | ||
@@ -40,0 +45,0 @@ addLocalVariable: (name: string) => void; |
@@ -24,5 +24,17 @@ "use strict"; | ||
}, | ||
navigationWithoutRename: { | ||
navigation: { | ||
shouldRename() { | ||
return false; | ||
}, | ||
}, | ||
}, | ||
navigationAndCompletion: { | ||
navigation: true, | ||
completion: true, | ||
}, | ||
navigationAndAdditionalCompletion: { | ||
navigation: true, | ||
completion: { isAdditional: true }, | ||
}, | ||
withoutHighlight: { | ||
@@ -44,3 +56,3 @@ semantic: { shouldHighlight: () => false }, | ||
}; | ||
function createTemplateCodegenContext() { | ||
function createTemplateCodegenContext(scriptSetupBindingNames) { | ||
let ignoredError = false; | ||
@@ -78,3 +90,3 @@ let expectErrorToken; | ||
const localVars = new Map(); | ||
const accessGlobalVariables = new Map(); | ||
const accessExternalVariables = new Map(); | ||
const slots = []; | ||
@@ -87,2 +99,3 @@ const dynamicSlots = []; | ||
const scopedClasses = []; | ||
const emptyClassOffsets = []; | ||
return { | ||
@@ -92,3 +105,3 @@ slots, | ||
codeFeatures, | ||
accessGlobalVariables, | ||
accessExternalVariables, | ||
hasSlotElements, | ||
@@ -98,6 +111,8 @@ blockConditions, | ||
scopedClasses, | ||
accessGlobalVariable(name, offset) { | ||
let arr = accessGlobalVariables.get(name); | ||
emptyClassOffsets, | ||
hasSlot: false, | ||
accessExternalVariable(name, offset) { | ||
let arr = accessExternalVariables.get(name); | ||
if (!arr) { | ||
accessGlobalVariables.set(name, arr = new Set()); | ||
accessExternalVariables.set(name, arr = new Set()); | ||
} | ||
@@ -153,3 +168,3 @@ if (offset !== undefined) { | ||
generateAutoImportCompletion: function* () { | ||
const all = [...accessGlobalVariables.entries()]; | ||
const all = [...accessExternalVariables.entries()]; | ||
if (!all.some(([_, offsets]) => offsets.size)) { | ||
@@ -162,8 +177,22 @@ return; | ||
for (const offset of offsets) { | ||
yield [ | ||
varName, | ||
'template', | ||
offset, | ||
codeFeatures.additionalCompletion, | ||
]; | ||
if (scriptSetupBindingNames.has(varName)) { | ||
// #3409 | ||
yield [ | ||
varName, | ||
'template', | ||
offset, | ||
{ | ||
...codeFeatures.additionalCompletion, | ||
...codeFeatures.withoutHighlightAndCompletionAndNavigation, | ||
}, | ||
]; | ||
} | ||
else { | ||
yield [ | ||
varName, | ||
'template', | ||
offset, | ||
codeFeatures.additionalCompletion, | ||
]; | ||
} | ||
yield `,`; | ||
@@ -170,0 +199,0 @@ } |
@@ -19,16 +19,18 @@ "use strict"; | ||
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 | ||
? [startTagOffset, endTagOffset] | ||
: [startTagOffset]; | ||
const propsFailedExps = []; | ||
const var_originalComponent = ctx.getInternalVariable(); | ||
const possibleOriginalNames = getPossibleOriginalComponentNames(node.tag, true); | ||
const matchImportName = possibleOriginalNames.find(name => options.scriptSetupImportComponentNames.has(name)); | ||
const var_originalComponent = matchImportName ?? ctx.getInternalVariable(); | ||
const var_functionalComponent = ctx.getInternalVariable(); | ||
const var_componentInstance = ctx.getInternalVariable(); | ||
const var_componentEmit = ctx.getInternalVariable(); | ||
const var_componentEvents = ctx.getInternalVariable(); | ||
const var_defineComponentCtx = ctx.getInternalVariable(); | ||
const isComponentTag = node.tag.toLowerCase() === 'component'; | ||
let endTagOffset = !node.isSelfClosing && options.template.lang === 'html' ? node.loc.start.offset + node.loc.source.lastIndexOf(node.tag) : undefined; | ||
let tag = node.tag; | ||
let tagOffsets = endTagOffset !== undefined | ||
? [startTagOffset, endTagOffset] | ||
: [startTagOffset]; | ||
let props = node.props; | ||
let dynamicTagInfo; | ||
let defineComponentCtxVar; | ||
let usedComponentEventsVar = false; | ||
@@ -48,6 +50,6 @@ if (isComponentTag) { | ||
} | ||
else if (tag.includes('.')) { | ||
else if (node.tag.includes('.')) { | ||
// namespace tag | ||
dynamicTagInfo = { | ||
exp: tag, | ||
exp: node.tag, | ||
astHolder: node.loc, | ||
@@ -57,3 +59,29 @@ offset: startTagOffset, | ||
} | ||
if (dynamicTagInfo) { | ||
if (matchImportName) { | ||
// hover, renaming / find references support | ||
yield `// @ts-ignore${common_1.newLine}`; // #2304 | ||
yield `[`; | ||
for (const tagOffset of tagOffsets) { | ||
if (var_originalComponent === node.tag) { | ||
yield [ | ||
var_originalComponent, | ||
'template', | ||
tagOffset, | ||
ctx.codeFeatures.withoutHighlightAndCompletion, | ||
]; | ||
} | ||
else { | ||
yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(node.tag), tagOffset, { | ||
...ctx.codeFeatures.withoutHighlightAndCompletion, | ||
navigation: { | ||
resolveRenameNewName: camelizeComponentName, | ||
resolveRenameEditText: getTagRenameApply(node.tag), | ||
}, | ||
}); | ||
} | ||
yield `,`; | ||
} | ||
yield `]${common_1.endOfLine}`; | ||
} | ||
else if (dynamicTagInfo) { | ||
yield `const ${var_originalComponent} = `; | ||
@@ -65,4 +93,4 @@ yield* (0, interpolation_1.generateInterpolation)(options, ctx, dynamicTagInfo.exp, dynamicTagInfo.astHolder, dynamicTagInfo.offset, ctx.codeFeatures.all, '(', ')'); | ||
yield `const ${var_originalComponent} = ({} as `; | ||
for (const componentName of getPossibleOriginalComponentNames(tag, true)) { | ||
yield `'${componentName}' extends keyof typeof __VLS_ctx ? { '${getCanonicalComponentName(tag)}': typeof __VLS_ctx`; | ||
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); | ||
@@ -72,17 +100,8 @@ yield ` }: `; | ||
yield `typeof __VLS_resolvedLocalAndGlobalComponents)`; | ||
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, getCanonicalComponentName(tag), startTagOffset, ctx.codeFeatures.verification); | ||
yield* (0, propertyAccess_1.generatePropertyAccess)(options, ctx, getCanonicalComponentName(node.tag), startTagOffset, ctx.codeFeatures.verification); | ||
yield common_1.endOfLine; | ||
} | ||
else { | ||
yield `const ${var_originalComponent} = {} as any${common_1.endOfLine}`; | ||
} | ||
yield `const ${var_functionalComponent} = __VLS_asFunctionalComponent(${var_originalComponent}, new ${var_originalComponent}({`; | ||
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, props, false); | ||
yield `}))${common_1.endOfLine}`; | ||
if (!dynamicTagInfo | ||
&& !isComponentTag) { | ||
// hover support | ||
for (const offset of tagOffsets) { | ||
yield `({} as { ${getCanonicalComponentName(tag)}: typeof ${var_originalComponent} }).`; | ||
yield* generateCanonicalComponentName(tag, offset, ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation); | ||
yield `({} as { ${getCanonicalComponentName(node.tag)}: typeof ${var_originalComponent} }).`; | ||
yield* generateCanonicalComponentName(node.tag, offset, ctx.codeFeatures.withoutHighlightAndCompletionAndNavigation); | ||
yield common_1.endOfLine; | ||
@@ -122,6 +141,12 @@ } | ||
} | ||
else { | ||
yield `const ${var_originalComponent} = {} as any${common_1.endOfLine}`; | ||
} | ||
yield `const ${var_functionalComponent} = __VLS_asFunctionalComponent(${var_originalComponent}, new ${var_originalComponent}({`; | ||
yield* (0, elementProps_1.generateElementProps)(options, ctx, node, props, false); | ||
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 + tag.length, ctx.codeFeatures.verification, `{`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, true, propsFailedExps), `}`); | ||
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}`; | ||
@@ -136,7 +161,6 @@ } | ||
yield `({} as (props: __VLS_FunctionalComponentProps<typeof ${var_originalComponent}, typeof ${var_componentInstance}> & Record<string, unknown>) => void)(`; | ||
yield* (0, common_1.wrapWith)(startTagOffset, startTagOffset + tag.length, ctx.codeFeatures.verification, `{`, ...(0, elementProps_1.generateElementProps)(options, ctx, node, props, true, propsFailedExps), `}`); | ||
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}`; | ||
} | ||
defineComponentCtxVar = ctx.getInternalVariable(); | ||
componentCtxVar = defineComponentCtxVar; | ||
componentCtxVar = var_defineComponentCtx; | ||
currentComponent = node; | ||
@@ -148,8 +172,6 @@ for (const failedExp of propsFailedExps) { | ||
yield* generateVScope(options, ctx, node, props); | ||
if (componentCtxVar) { | ||
ctx.usedComponentCtxVars.add(componentCtxVar); | ||
yield* (0, elementEvents_1.generateElementEvents)(options, ctx, node, var_functionalComponent, var_componentInstance, var_componentEvents, () => usedComponentEventsVar = true); | ||
} | ||
ctx.usedComponentCtxVars.add(componentCtxVar); | ||
yield* (0, elementEvents_1.generateElementEvents)(options, ctx, node, var_functionalComponent, var_componentInstance, var_componentEmit, var_componentEvents, () => usedComponentEventsVar = true); | ||
const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot'); | ||
if (slotDir && componentCtxVar) { | ||
if (slotDir) { | ||
yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, componentCtxVar); | ||
@@ -160,7 +182,8 @@ } | ||
} | ||
if (defineComponentCtxVar && ctx.usedComponentCtxVars.has(defineComponentCtxVar)) { | ||
if (var_defineComponentCtx && ctx.usedComponentCtxVars.has(var_defineComponentCtx)) { | ||
yield `const ${componentCtxVar} = __VLS_pickFunctionalComponentCtx(${var_originalComponent}, ${var_componentInstance})!${common_1.endOfLine}`; | ||
} | ||
if (usedComponentEventsVar) { | ||
yield `let ${var_componentEvents}!: __VLS_NormalizeEmits<typeof ${componentCtxVar}.emit>${common_1.endOfLine}`; | ||
yield `let ${var_componentEmit}!: typeof ${componentCtxVar}.emit${common_1.endOfLine}`; | ||
yield `let ${var_componentEvents}!: __VLS_NormalizeEmits<typeof ${var_componentEmit}>${common_1.endOfLine}`; | ||
} | ||
@@ -219,5 +242,3 @@ } | ||
yield* generateReferencesForElements(options, ctx, node); // <el ref="foo" /> | ||
if (options.shouldGenerateScopedClasses) { | ||
yield* generateReferencesForScopedCssClasses(ctx, node); | ||
} | ||
yield* generateReferencesForScopedCssClasses(ctx, node); | ||
if (inScope) { | ||
@@ -352,16 +373,27 @@ yield `}${common_1.newLine}`; | ||
let startOffset = prop.value.loc.start.offset; | ||
let tempClassName = ''; | ||
for (const char of (prop.value.loc.source + ' ')) { | ||
if (char.trim() === '' || char === '"' || char === "'") { | ||
if (tempClassName !== '') { | ||
ctx.scopedClasses.push({ className: tempClassName, offset: startOffset }); | ||
startOffset += tempClassName.length; | ||
tempClassName = ''; | ||
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; | ||
} | ||
startOffset += char.length; | ||
else { | ||
currentClassName += char; | ||
} | ||
} | ||
else { | ||
tempClassName += char; | ||
} | ||
} | ||
else { | ||
ctx.emptyClassOffsets.push(startOffset); | ||
} | ||
} | ||
@@ -368,0 +400,0 @@ else if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE |
@@ -19,3 +19,3 @@ "use strict"; | ||
&& prop.name !== 'data') { | ||
ctx.accessGlobalVariable((0, shared_1.camelize)('v-' + prop.name), prop.loc.start.offset); | ||
ctx.accessExternalVariable((0, shared_1.camelize)('v-' + prop.name), prop.loc.start.offset); | ||
if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && !prop.arg.isStatic) { | ||
@@ -22,0 +22,0 @@ yield* (0, interpolation_1.generateInterpolation)(options, ctx, prop.arg.content, prop.arg.loc, prop.arg.loc.start.offset + prop.arg.loc.source.indexOf(prop.arg.content), ctx.codeFeatures.all, '(', ')'); |
@@ -6,5 +6,5 @@ import * as CompilerDOM from '@vue/compiler-dom'; | ||
import type { TemplateCodegenOptions } from './index'; | ||
export declare function generateElementEvents(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, componentVar: string, componentInstanceVar: string, eventsVar: string, used: () => void): Generator<Code>; | ||
export declare function generateEventArg(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, arg: CompilerDOM.SimpleExpressionNode, access: boolean): Generator<Code>; | ||
export declare function generateElementEvents(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, node: CompilerDOM.ElementNode, componentVar: string, componentInstanceVar: string, emitVar: string, eventsVar: string, used: () => void): Generator<Code>; | ||
export declare function generateEventArg(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, arg: CompilerDOM.SimpleExpressionNode, access: boolean, enableHover: boolean): Generator<Code>; | ||
export declare function generateEventExpression(options: TemplateCodegenOptions, ctx: TemplateCodegenContext, prop: CompilerDOM.DirectiveNode): Generator<Code>; | ||
export declare function isCompoundExpression(ts: typeof import('typescript'), ast: ts.SourceFile): boolean; |
@@ -11,3 +11,3 @@ "use strict"; | ||
const objectProperty_1 = require("./objectProperty"); | ||
function* generateElementEvents(options, ctx, node, componentVar, componentInstanceVar, eventsVar, used) { | ||
function* generateElementEvents(options, ctx, node, componentVar, componentInstanceVar, emitVar, eventsVar, used) { | ||
for (const prop of node.props) { | ||
@@ -19,6 +19,8 @@ if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE | ||
const eventVar = ctx.getInternalVariable(); | ||
yield `let ${eventVar} = { '${prop.arg.loc.source}': __VLS_pickEvent(`; | ||
yield `let ${eventVar} = {${common_1.newLine}`; | ||
yield `/**__VLS_emit,${emitVar},${prop.arg.loc.source}*/${common_1.newLine}`; | ||
yield `'${prop.arg.loc.source}': __VLS_pickEvent(`; | ||
yield `${eventsVar}['${prop.arg.loc.source}'], `; | ||
yield `({} as __VLS_FunctionalComponentProps<typeof ${componentVar}, typeof ${componentInstanceVar}>)`; | ||
yield* generateEventArg(options, ctx, prop.arg, true); | ||
yield* generateEventArg(options, ctx, prop.arg, true, false); | ||
yield `) }${common_1.endOfLine}`; | ||
@@ -36,3 +38,4 @@ yield `${eventVar} = { `; | ||
yield* generateEventExpression(options, ctx, prop); | ||
yield ` }${common_1.endOfLine}`; | ||
yield common_1.newLine; | ||
yield `}${common_1.endOfLine}`; | ||
} | ||
@@ -66,3 +69,9 @@ else if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE | ||
}; | ||
function* generateEventArg(options, ctx, arg, access) { | ||
function* generateEventArg(options, ctx, arg, access, enableHover) { | ||
const features = enableHover | ||
? { | ||
...ctx.codeFeatures.withoutHighlightAndCompletion, | ||
...eventArgFeatures, | ||
} | ||
: eventArgFeatures; | ||
if (arg.loc.source.startsWith('[') && arg.loc.source.endsWith(']')) { | ||
@@ -77,3 +86,3 @@ yield `[`; | ||
} | ||
yield ['', 'template', arg.loc.start.offset, eventArgFeatures]; | ||
yield ['', 'template', arg.loc.start.offset, features]; | ||
yield `on`; | ||
@@ -86,3 +95,3 @@ yield* (0, camelized_1.generateCamelized)((0, shared_1.capitalize)(arg.loc.source), arg.loc.start.offset, common_1.combineLastMapping); | ||
} | ||
yield* (0, common_1.wrapWith)(arg.loc.start.offset, arg.loc.end.offset, eventArgFeatures, `'`, ['', 'template', arg.loc.start.offset, common_1.combineLastMapping], 'on', ...(0, camelized_1.generateCamelized)((0, shared_1.capitalize)(arg.loc.source), arg.loc.start.offset, common_1.combineLastMapping), `'`); | ||
yield* (0, common_1.wrapWith)(arg.loc.start.offset, arg.loc.end.offset, features, `'`, ['', 'template', arg.loc.start.offset, common_1.combineLastMapping], 'on', ...(0, camelized_1.generateCamelized)((0, shared_1.capitalize)(arg.loc.source), arg.loc.start.offset, common_1.combineLastMapping), `'`); | ||
if (access) { | ||
@@ -89,0 +98,0 @@ yield `]`; |
@@ -27,3 +27,19 @@ "use strict"; | ||
} | ||
if (!isIntrinsicElement) { | ||
if (isIntrinsicElement) { | ||
for (const prop of props) { | ||
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE | ||
&& prop.name === 'on') { | ||
if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) { | ||
yield* (0, elementEvents_1.generateEventArg)(options, ctx, prop.arg, false, true); | ||
yield `: `; | ||
yield* (0, elementEvents_1.generateEventExpression)(options, ctx, prop); | ||
yield `,${common_1.newLine}`; | ||
} | ||
else if (prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) { | ||
propsFailedExps?.push(prop.exp); | ||
} | ||
} | ||
} | ||
} | ||
else { | ||
let generatedEvent = false; | ||
@@ -48,14 +64,2 @@ for (const prop of props) { | ||
} | ||
else { | ||
for (const prop of props) { | ||
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE | ||
&& prop.name === 'on' | ||
&& prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) { | ||
yield* (0, elementEvents_1.generateEventArg)(options, ctx, prop.arg, false); | ||
yield `: `; | ||
yield* (0, elementEvents_1.generateEventExpression)(options, ctx, prop); | ||
yield `,${common_1.newLine}`; | ||
} | ||
} | ||
} | ||
for (const prop of props) { | ||
@@ -177,3 +181,3 @@ if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE | ||
if (!ctx.hasLocalVariable(propVariableName)) { | ||
ctx.accessGlobalVariable(propVariableName, exp.loc.start.offset); | ||
ctx.accessExternalVariable(propVariableName, exp.loc.start.offset); | ||
yield `__VLS_ctx.`; | ||
@@ -180,0 +184,0 @@ } |
import * as CompilerDOM from '@vue/compiler-dom'; | ||
import type * as ts from 'typescript'; | ||
import type { Code, Sfc, VueCompilerOptions } from '../../types'; | ||
import { TemplateCodegenContext } from './context'; | ||
export interface TemplateCodegenOptions { | ||
@@ -9,4 +10,4 @@ ts: typeof ts; | ||
template: NonNullable<Sfc['template']>; | ||
shouldGenerateScopedClasses?: boolean; | ||
stylesScopedClasses: Set<string>; | ||
scriptSetupBindingNames: Set<string>; | ||
scriptSetupImportComponentNames: Set<string>; | ||
hasDefineSlots?: boolean; | ||
@@ -16,47 +17,4 @@ slotsAssignName?: string; | ||
} | ||
export declare function generateTemplate(options: TemplateCodegenOptions): Generator<Code, { | ||
ctx: { | ||
slots: { | ||
name: string; | ||
loc?: number | undefined; | ||
tagRange: [number, number]; | ||
varName: string; | ||
nodeLoc: any; | ||
}[]; | ||
dynamicSlots: { | ||
expVar: string; | ||
varName: string; | ||
}[]; | ||
codeFeatures: { | ||
all: import("../../types").VueCodeInformation; | ||
verification: import("../../types").VueCodeInformation; | ||
completion: import("../../types").VueCodeInformation; | ||
additionalCompletion: import("../../types").VueCodeInformation; | ||
navigation: import("../../types").VueCodeInformation; | ||
navigationAndCompletion: import("../../types").VueCodeInformation; | ||
withoutHighlight: import("../../types").VueCodeInformation; | ||
withoutHighlightAndCompletion: import("../../types").VueCodeInformation; | ||
withoutHighlightAndCompletionAndNavigation: import("../../types").VueCodeInformation; | ||
}; | ||
accessGlobalVariables: Map<string, Set<number>>; | ||
hasSlotElements: Set<CompilerDOM.ElementNode>; | ||
blockConditions: string[]; | ||
usedComponentCtxVars: Set<string>; | ||
scopedClasses: { | ||
className: string; | ||
offset: number; | ||
}[]; | ||
accessGlobalVariable(name: string, offset?: number | undefined): void; | ||
hasLocalVariable: (name: string) => boolean; | ||
addLocalVariable: (name: string) => void; | ||
removeLocalVariable: (name: string) => void; | ||
getInternalVariable: () => string; | ||
ignoreError: () => Generator<Code, any, unknown>; | ||
expectError: (prevNode: CompilerDOM.CommentNode) => Generator<Code, any, unknown>; | ||
resetDirectiveComments: (endStr: string) => Generator<Code, any, unknown>; | ||
generateAutoImportCompletion: () => Generator<Code, any, unknown>; | ||
}; | ||
hasSlot: boolean; | ||
}, unknown>; | ||
export declare function generateTemplate(options: TemplateCodegenOptions): Generator<Code, TemplateCodegenContext>; | ||
export declare function forEachElementNode(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode): Generator<CompilerDOM.ElementNode>; | ||
export declare function isFragment(node: CompilerDOM.IfNode | CompilerDOM.ForNode): boolean | undefined; |
@@ -9,7 +9,5 @@ "use strict"; | ||
const objectProperty_1 = require("./objectProperty"); | ||
const stringLiteralKey_1 = require("./stringLiteralKey"); | ||
const templateChild_1 = require("./templateChild"); | ||
function* generateTemplate(options) { | ||
const ctx = (0, context_1.createTemplateCodegenContext)(); | ||
let hasSlot = false; | ||
const ctx = (0, context_1.createTemplateCodegenContext)(options.scriptSetupBindingNames); | ||
if (options.slotsAssignName) { | ||
@@ -32,9 +30,6 @@ ctx.addLocalVariable(options.slotsAssignName); | ||
yield* ctx.generateAutoImportCompletion(); | ||
return { | ||
ctx, | ||
hasSlot, | ||
}; | ||
return ctx; | ||
function* generateSlotsType() { | ||
for (const { expVar, varName } of ctx.dynamicSlots) { | ||
hasSlot = true; | ||
ctx.hasSlot = true; | ||
yield `Partial<Record<NonNullable<typeof ${expVar}>, (_: typeof ${varName}) => any>> &${common_1.newLine}`; | ||
@@ -44,14 +39,8 @@ } | ||
for (const slot of ctx.slots) { | ||
hasSlot = true; | ||
ctx.hasSlot = true; | ||
if (slot.name && slot.loc !== undefined) { | ||
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slot.name, slot.loc, { | ||
...ctx.codeFeatures.withoutHighlightAndCompletion, | ||
__referencesCodeLens: true, | ||
}, slot.nodeLoc); | ||
yield* (0, objectProperty_1.generateObjectProperty)(options, ctx, slot.name, slot.loc, ctx.codeFeatures.withoutHighlightAndCompletion, slot.nodeLoc); | ||
} | ||
else { | ||
yield* (0, common_1.wrapWith)(slot.tagRange[0], slot.tagRange[1], { | ||
...ctx.codeFeatures.withoutHighlightAndCompletion, | ||
__referencesCodeLens: true, | ||
}, `default`); | ||
yield* (0, common_1.wrapWith)(slot.tagRange[0], slot.tagRange[1], ctx.codeFeatures.withoutHighlightAndCompletion, `default`); | ||
} | ||
@@ -64,8 +53,34 @@ yield `?(_: typeof ${slot.varName}): any,${common_1.newLine}`; | ||
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}`; | ||
} | ||
for (const { className, offset } of ctx.scopedClasses) { | ||
yield `__VLS_styleScopedClasses[`; | ||
yield* (0, stringLiteralKey_1.generateStringLiteralKey)(className, offset, { | ||
...ctx.codeFeatures.navigationAndCompletion, | ||
__displayWithLink: options.stylesScopedClasses.has(className), | ||
}); | ||
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}`; | ||
@@ -72,0 +87,0 @@ } |
import type * as ts from 'typescript'; | ||
import type { Code, VueCodeInformation, VueCompilerOptions } from '../../types'; | ||
import type { Code, VueCodeInformation } from '../../types'; | ||
import type { TemplateCodegenContext } from './context'; | ||
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 forEachInterpolationSegment(ts: typeof import('typescript'), vueOptions: VueCompilerOptions, ctx: TemplateCodegenContext, code: string, offset: number | undefined, ast: ts.SourceFile): Generator<[fragment: string, offset: number | undefined, isJustForErrorMapping?: boolean]>; | ||
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]>; |
@@ -11,3 +11,3 @@ "use strict"; | ||
const vars = []; | ||
for (let [section, offset, onlyError] of forEachInterpolationSegment(options.ts, options.vueCompilerOptions, ctx, code, start !== undefined ? start - prefix.length : undefined, ast)) { | ||
for (let [section, offset, onlyError] of forEachInterpolationSegment(options.ts, ctx, code, start !== undefined ? start - prefix.length : undefined, ast)) { | ||
if (offset === undefined) { | ||
@@ -52,3 +52,3 @@ yield section; | ||
exports.generateInterpolation = generateInterpolation; | ||
function* forEachInterpolationSegment(ts, vueOptions, ctx, code, offset, ast) { | ||
function* forEachInterpolationSegment(ts, ctx, code, offset, ast) { | ||
let ctxVars = []; | ||
@@ -71,6 +71,6 @@ const varCb = (id, isShorthand) => { | ||
if (offset !== undefined) { | ||
ctx.accessGlobalVariable(text, offset + (0, scriptSetupRanges_1.getStartEnd)(ts, id, ast).start); | ||
ctx.accessExternalVariable(text, offset + (0, scriptSetupRanges_1.getStartEnd)(ts, id, ast).start); | ||
} | ||
else { | ||
ctx.accessGlobalVariable(text); | ||
ctx.accessExternalVariable(text); | ||
} | ||
@@ -93,48 +93,14 @@ } | ||
yield ['', ctxVars[i + 1].offset, true]; | ||
if (vueOptions.experimentalUseElementAccessInTemplate) { | ||
const varStart = ctxVars[i].offset; | ||
const varEnd = ctxVars[i].offset + ctxVars[i].text.length; | ||
yield ['__VLS_ctx[', undefined]; | ||
yield ['', varStart, true]; | ||
yield ["'", undefined]; | ||
yield [code.substring(varStart, varEnd), varStart]; | ||
yield ["'", undefined]; | ||
yield ['', varEnd, true]; | ||
yield [']', undefined]; | ||
if (ctxVars[i + 1].isShorthand) { | ||
yield [code.substring(varEnd, ctxVars[i + 1].offset + ctxVars[i + 1].text.length), varEnd]; | ||
yield [': ', undefined]; | ||
} | ||
else { | ||
yield [code.substring(varEnd, ctxVars[i + 1].offset), varEnd]; | ||
} | ||
yield ['__VLS_ctx.', undefined]; | ||
if (ctxVars[i + 1].isShorthand) { | ||
yield [code.substring(ctxVars[i].offset, ctxVars[i + 1].offset + ctxVars[i + 1].text.length), ctxVars[i].offset]; | ||
yield [': ', undefined]; | ||
} | ||
else { | ||
yield ['__VLS_ctx.', undefined]; | ||
if (ctxVars[i + 1].isShorthand) { | ||
yield [code.substring(ctxVars[i].offset, ctxVars[i + 1].offset + ctxVars[i + 1].text.length), ctxVars[i].offset]; | ||
yield [': ', undefined]; | ||
} | ||
else { | ||
yield [code.substring(ctxVars[i].offset, ctxVars[i + 1].offset), ctxVars[i].offset]; | ||
} | ||
yield [code.substring(ctxVars[i].offset, ctxVars[i + 1].offset), ctxVars[i].offset]; | ||
} | ||
} | ||
if (vueOptions.experimentalUseElementAccessInTemplate) { | ||
const varStart = ctxVars[ctxVars.length - 1].offset; | ||
const varEnd = ctxVars[ctxVars.length - 1].offset + ctxVars[ctxVars.length - 1].text.length; | ||
yield ['__VLS_ctx[', undefined]; | ||
yield ['', varStart, true]; | ||
yield ["'", undefined]; | ||
yield [code.substring(varStart, varEnd), varStart]; | ||
yield ["'", undefined]; | ||
yield ['', varEnd, true]; | ||
yield [']', undefined]; | ||
yield [code.substring(varEnd), varEnd]; | ||
} | ||
else { | ||
yield ['', ctxVars[ctxVars.length - 1].offset, true]; | ||
yield ['__VLS_ctx.', undefined]; | ||
yield [code.substring(ctxVars[ctxVars.length - 1].offset), ctxVars[ctxVars.length - 1].offset]; | ||
} | ||
yield ['', ctxVars[ctxVars.length - 1].offset, true]; | ||
yield ['__VLS_ctx.', undefined]; | ||
yield [code.substring(ctxVars[ctxVars.length - 1].offset), ctxVars[ctxVars.length - 1].offset]; | ||
} | ||
@@ -141,0 +107,0 @@ else { |
@@ -9,2 +9,2 @@ import { type LanguagePlugin } from '@volar/language-core'; | ||
} | ||
export declare function createVueLanguagePlugin(ts: typeof import('typescript'), getFileName: (fileId: string) => string, useCaseSensitiveFileNames: boolean, getProjectVersion: () => string, getScriptFileNames: () => string[] | Set<string>, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions): _Plugin; | ||
export declare function createVueLanguagePlugin(ts: typeof import('typescript'), getFileName: (scriptId: string) => string, useCaseSensitiveFileNames: boolean, getProjectVersion: () => string, getScriptFileNames: () => string[] | Set<string>, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions): _Plugin; |
@@ -79,5 +79,5 @@ "use strict"; | ||
}, | ||
createVirtualCode(fileId, languageId, snapshot) { | ||
createVirtualCode(scriptId, languageId, snapshot) { | ||
if (languageId === 'vue' || languageId === 'markdown' || languageId === 'html') { | ||
const fileName = getFileName(fileId); | ||
const fileName = getFileName(scriptId); | ||
const projectVersion = getProjectVersion(); | ||
@@ -92,3 +92,3 @@ if (projectVersion !== canonicalRootFileNamesVersion) { | ||
const fileRegistry = getFileRegistry(pluginContext.globalTypesHolder === fileName); | ||
const code = fileRegistry.get(fileId); | ||
const code = fileRegistry.get(scriptId); | ||
if (code) { | ||
@@ -104,3 +104,3 @@ code.update(snapshot); | ||
: [vueSfcPlugin, ...basePlugins], ts); | ||
fileRegistry.set(fileId, code); | ||
fileRegistry.set(scriptId, code); | ||
return code; | ||
@@ -107,0 +107,0 @@ } |
@@ -14,3 +14,4 @@ import type { TextRange } from '../types'; | ||
}) | undefined; | ||
classBlockEnd: number | undefined; | ||
bindings: TextRange[]; | ||
}; |
@@ -7,2 +7,3 @@ "use strict"; | ||
let exportDefault; | ||
let classBlockEnd; | ||
const bindings = hasScriptSetup ? (0, scriptSetupRanges_1.parseBindingRanges)(ts, ast) : []; | ||
@@ -50,5 +51,11 @@ ts.forEachChild(ast, raw => { | ||
} | ||
if (ts.isClassDeclaration(raw) | ||
&& raw.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword) | ||
&& raw.modifiers?.some(mod => mod.kind === ts.SyntaxKind.DefaultKeyword)) { | ||
classBlockEnd = raw.end - 1; | ||
} | ||
}); | ||
return { | ||
exportDefault, | ||
classBlockEnd, | ||
bindings, | ||
@@ -55,0 +62,0 @@ }; |
@@ -9,2 +9,3 @@ import type * as ts from 'typescript'; | ||
bindings: TextRange[]; | ||
importComponentNames: Set<string>; | ||
props: { | ||
@@ -53,2 +54,5 @@ name?: string | undefined; | ||
}[]; | ||
options: { | ||
name?: string | undefined; | ||
}; | ||
}; | ||
@@ -55,0 +59,0 @@ export declare function parseBindingRanges(ts: typeof import('typescript'), sourceFile: ts.SourceFile): TextRange[]; |
@@ -11,2 +11,3 @@ "use strict"; | ||
const expose = {}; | ||
const options = {}; | ||
const definePropProposalA = vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition'); | ||
@@ -18,2 +19,3 @@ const definePropProposalB = vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition' || ast.text.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition'); | ||
const leadingCommentEndOffset = ts.getLeadingCommentRanges(text, 0)?.reverse()[0].end ?? 0; | ||
const importComponentNames = new Set(); | ||
ts.forEachChild(ast, node => { | ||
@@ -37,2 +39,10 @@ const isTypeExport = (ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword); | ||
} | ||
if (ts.isImportDeclaration(node) | ||
&& node.importClause?.name | ||
&& !node.importClause.isTypeOnly) { | ||
const moduleName = getNodeText(ts, node.moduleSpecifier, ast).slice(1, -1); | ||
if (vueCompilerOptions.extensions.some(ext => moduleName.endsWith(ext))) { | ||
importComponentNames.add(getNodeText(ts, node.importClause.name, ast)); | ||
} | ||
} | ||
}); | ||
@@ -44,2 +54,3 @@ ts.forEachChild(ast, child => visitNode(child, [ast])); | ||
bindings, | ||
importComponentNames, | ||
props, | ||
@@ -50,2 +61,3 @@ slots, | ||
defineProp, | ||
options, | ||
}; | ||
@@ -204,2 +216,11 @@ function _getStartEnd(node) { | ||
} | ||
else if (vueCompilerOptions.macros.defineOptions.includes(callText)) { | ||
if (node.arguments.length && ts.isObjectLiteralExpression(node.arguments[0])) { | ||
for (const prop of node.arguments[0].properties) { | ||
if ((ts.isPropertyAssignment(prop)) && getNodeText(ts, prop.name, ast) === 'name' && ts.isStringLiteral(prop.initializer)) { | ||
options.name = prop.initializer.text; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
@@ -246,2 +267,5 @@ ts.forEachChild(node, child => { | ||
for (const element of node.importClause.namedBindings.elements) { | ||
if (element.isTypeOnly) { | ||
continue; | ||
} | ||
bindings.push(_getStartEnd(element.name)); | ||
@@ -248,0 +272,0 @@ } |
@@ -77,3 +77,3 @@ "use strict"; | ||
) { | ||
if (prop.name === 'on') { | ||
if (prop.name === 'on' && prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) { | ||
const ast = (0, common_1.createTsAst)(ctx.modules.typescript, prop.exp, prop.exp.content); | ||
@@ -80,0 +80,0 @@ addFormatCodes(prop.exp.content, prop.exp.loc.start.offset, (0, elementEvents_1.isCompoundExpression)(ctx.modules.typescript, ast) |
@@ -13,2 +13,3 @@ import type { Mapping } from '@volar/language-core'; | ||
}) | undefined; | ||
classBlockEnd: number | undefined; | ||
bindings: import("../types").TextRange[]; | ||
@@ -20,2 +21,3 @@ } | undefined; | ||
bindings: import("../types").TextRange[]; | ||
importComponentNames: Set<string>; | ||
props: { | ||
@@ -64,2 +66,5 @@ name?: string | undefined; | ||
}[]; | ||
options: { | ||
name?: string | undefined; | ||
}; | ||
} | undefined; | ||
@@ -73,44 +78,45 @@ lang: () => string; | ||
codes: Code[]; | ||
ctx: { | ||
slots: { | ||
name: string; | ||
loc?: number | undefined; | ||
tagRange: [number, number]; | ||
varName: string; | ||
nodeLoc: any; | ||
}[]; | ||
dynamicSlots: { | ||
expVar: string; | ||
varName: string; | ||
}[]; | ||
codeFeatures: { | ||
all: import("../types").VueCodeInformation; | ||
verification: import("../types").VueCodeInformation; | ||
completion: import("../types").VueCodeInformation; | ||
additionalCompletion: import("../types").VueCodeInformation; | ||
navigation: import("../types").VueCodeInformation; | ||
navigationAndCompletion: import("../types").VueCodeInformation; | ||
withoutHighlight: import("../types").VueCodeInformation; | ||
withoutHighlightAndCompletion: import("../types").VueCodeInformation; | ||
withoutHighlightAndCompletionAndNavigation: import("../types").VueCodeInformation; | ||
}; | ||
accessGlobalVariables: Map<string, Set<number>>; | ||
hasSlotElements: Set<import("@vue/compiler-dom").ElementNode>; | ||
blockConditions: string[]; | ||
usedComponentCtxVars: Set<string>; | ||
scopedClasses: { | ||
className: string; | ||
offset: number; | ||
}[]; | ||
accessGlobalVariable(name: string, offset?: number | undefined): void; | ||
hasLocalVariable: (name: string) => boolean; | ||
addLocalVariable: (name: string) => void; | ||
removeLocalVariable: (name: string) => void; | ||
getInternalVariable: () => string; | ||
ignoreError: () => Generator<Code, any, unknown>; | ||
expectError: (prevNode: import("@vue/compiler-dom").CommentNode) => Generator<Code, any, unknown>; | ||
resetDirectiveComments: (endStr: string) => Generator<Code, any, unknown>; | ||
generateAutoImportCompletion: () => Generator<Code, any, unknown>; | ||
slots: { | ||
name: string; | ||
loc?: number | undefined; | ||
tagRange: [number, number]; | ||
varName: string; | ||
nodeLoc: any; | ||
}[]; | ||
dynamicSlots: { | ||
expVar: string; | ||
varName: string; | ||
}[]; | ||
codeFeatures: { | ||
all: import("../types").VueCodeInformation; | ||
verification: import("../types").VueCodeInformation; | ||
completion: import("../types").VueCodeInformation; | ||
additionalCompletion: import("../types").VueCodeInformation; | ||
navigation: import("../types").VueCodeInformation; | ||
navigationWithoutRename: import("../types").VueCodeInformation; | ||
navigationAndCompletion: import("../types").VueCodeInformation; | ||
navigationAndAdditionalCompletion: import("../types").VueCodeInformation; | ||
withoutHighlight: import("../types").VueCodeInformation; | ||
withoutHighlightAndCompletion: import("../types").VueCodeInformation; | ||
withoutHighlightAndCompletionAndNavigation: import("../types").VueCodeInformation; | ||
}; | ||
accessExternalVariables: Map<string, Set<number>>; | ||
hasSlotElements: Set<import("@vue/compiler-dom").ElementNode>; | ||
blockConditions: string[]; | ||
usedComponentCtxVars: Set<string>; | ||
scopedClasses: { | ||
className: string; | ||
offset: number; | ||
}[]; | ||
emptyClassOffsets: number[]; | ||
hasSlot: boolean; | ||
accessExternalVariable(name: string, offset?: number | undefined): void; | ||
hasLocalVariable: (name: string) => boolean; | ||
addLocalVariable: (name: string) => void; | ||
removeLocalVariable: (name: string) => void; | ||
getInternalVariable: () => string; | ||
ignoreError: () => Generator<Code, any, unknown>; | ||
expectError: (prevNode: import("@vue/compiler-dom").CommentNode) => Generator<Code, any, unknown>; | ||
resetDirectiveComments: (endStr: string) => Generator<Code, any, unknown>; | ||
generateAutoImportCompletion: () => Generator<Code, any, unknown>; | ||
} | undefined; | ||
@@ -117,0 +123,0 @@ }>; |
@@ -60,23 +60,2 @@ "use strict"; | ||
: undefined); | ||
const shouldGenerateScopedClasses = (0, computeds_1.computed)(() => { | ||
const option = ctx.vueCompilerOptions.experimentalResolveStyleCssClasses; | ||
return _sfc.styles.some(s => { | ||
return option === 'always' || (option === 'scoped' && s.scoped); | ||
}); | ||
}); | ||
const stylesScopedClasses = (0, computeds_1.computedSet)(() => { | ||
const classes = new Set(); | ||
if (!shouldGenerateScopedClasses()) { | ||
return classes; | ||
} | ||
for (const style of _sfc.styles) { | ||
const option = ctx.vueCompilerOptions.experimentalResolveStyleCssClasses; | ||
if (option === 'always' || (option === 'scoped' && style.scoped)) { | ||
for (const className of style.classNames) { | ||
classes.add(className.text.substring(1)); | ||
} | ||
} | ||
} | ||
return classes; | ||
}); | ||
const generatedTemplate = (0, computeds_1.computed)(() => { | ||
@@ -92,4 +71,4 @@ if (!_sfc.template) { | ||
template: _sfc.template, | ||
shouldGenerateScopedClasses: shouldGenerateScopedClasses(), | ||
stylesScopedClasses: stylesScopedClasses(), | ||
scriptSetupBindingNames: scriptSetupBindingNames(), | ||
scriptSetupImportComponentNames: scriptSetupImportComponentNames(), | ||
hasDefineSlots: hasDefineSlots(), | ||
@@ -111,2 +90,22 @@ slotsAssignName: slotsAssignName(), | ||
const hasDefineSlots = (0, computeds_1.computed)(() => !!scriptSetupRanges()?.slots.define); | ||
const scriptSetupBindingNames = (0, computeds_1.computed)(oldNames => { | ||
const newNames = new Set(); | ||
const bindings = scriptSetupRanges()?.bindings; | ||
if (_sfc.scriptSetup && bindings) { | ||
for (const binding of bindings) { | ||
newNames.add(_sfc.scriptSetup?.content.substring(binding.start, binding.end)); | ||
} | ||
} | ||
if (newNames && oldNames && twoSetsEqual(newNames, oldNames)) { | ||
return oldNames; | ||
} | ||
return newNames; | ||
}); | ||
const scriptSetupImportComponentNames = (0, computeds_1.computed)(oldNames => { | ||
const newNames = scriptSetupRanges()?.importComponentNames ?? new Set(); | ||
if (newNames && oldNames && twoSetsEqual(newNames, oldNames)) { | ||
return oldNames; | ||
} | ||
return newNames; | ||
}); | ||
const slotsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.slots.name); | ||
@@ -127,7 +126,3 @@ const propsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.props.name); | ||
scriptSetupRanges: scriptSetupRanges(), | ||
templateCodegen: _template ? { | ||
tsCodes: _template.codes, | ||
ctx: _template.ctx, | ||
hasSlot: _template.hasSlot, | ||
} : undefined, | ||
templateCodegen: _template, | ||
compilerOptions: ctx.compilerOptions, | ||
@@ -157,2 +152,13 @@ vueCompilerOptions: ctx.vueCompilerOptions, | ||
} | ||
function twoSetsEqual(a, b) { | ||
if (a.size !== b.size) { | ||
return false; | ||
} | ||
for (const file of a) { | ||
if (!b.has(file)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
//# sourceMappingURL=vue-tsx.js.map |
@@ -13,4 +13,2 @@ import type * as CompilerDOM from '@vue/compiler-dom'; | ||
export interface VueCodeInformation extends CodeInformation { | ||
__referencesCodeLens?: boolean; | ||
__displayWithLink?: boolean; | ||
__hint?: { | ||
@@ -52,3 +50,2 @@ setting: string; | ||
experimentalModelPropName: Record<string, Record<string, boolean | Record<string, string> | Record<string, string>[]>>; | ||
experimentalUseElementAccessInTemplate: boolean; | ||
} | ||
@@ -129,14 +126,2 @@ export declare const pluginVersion = 2; | ||
})[]; | ||
/** | ||
* @deprecated use `template.ast` instead | ||
*/ | ||
templateAst: CompilerDOM.RootNode | undefined; | ||
/** | ||
* @deprecated use `script.ast` instead | ||
*/ | ||
scriptAst: ts.SourceFile | undefined; | ||
/** | ||
* @deprecated use `scriptSetup.ast` instead | ||
*/ | ||
scriptSetupAst: ts.SourceFile | undefined; | ||
} | ||
@@ -143,0 +128,0 @@ export interface TextRange { |
@@ -5,3 +5,3 @@ "use strict"; | ||
const parseCssVars_1 = require("./parseCssVars"); | ||
const cssClassNameReg = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\+\{\>#\:]{1})/g; | ||
const cssClassNameReg = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\,\+\{\>#\:]{1})/g; | ||
function* parseCssClassNames(styleContent) { | ||
@@ -8,0 +8,0 @@ styleContent = (0, parseCssVars_1.clearComments)(styleContent); |
@@ -213,3 +213,2 @@ "use strict"; | ||
}, | ||
experimentalUseElementAccessInTemplate: vueOptions.experimentalUseElementAccessInTemplate ?? false, | ||
}; | ||
@@ -216,0 +215,0 @@ } |
@@ -98,5 +98,2 @@ "use strict"; | ||
get customBlocks() { return customBlocks; }, | ||
get templateAst() { return template()?.ast; }, | ||
get scriptAst() { return script()?.ast; }, | ||
get scriptSetupAst() { return scriptSetup()?.ast; }, | ||
}; | ||
@@ -103,0 +100,0 @@ function computedTemplateAst(base) { |
{ | ||
"name": "@vue/language-core", | ||
"version": "2.0.16", | ||
"version": "2.0.17", | ||
"license": "MIT", | ||
@@ -15,3 +15,3 @@ "files": [ | ||
"dependencies": { | ||
"@volar/language-core": "~2.2.0", | ||
"@volar/language-core": "~2.2.2", | ||
"@vue/compiler-dom": "^3.4.0", | ||
@@ -38,3 +38,3 @@ "@vue/shared": "^3.4.0", | ||
}, | ||
"gitHead": "95b78c38cbf75481ebb59e11956b592346f01d92" | ||
"gitHead": "968039cbb07961f318b4bf122bfa8e3e4a824277" | ||
} |
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
292465
6496
Updated@volar/language-core@~2.2.2