Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/language-core/lib/codegen/template/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
}[] = [];
const hasSlotElements = new Set<CompilerDOM.ElementNode>();;
const blockConditions: string[] = [];
const usedComponentCtxVars = new Set<string>();
const scopedClasses: {
source: string;
className: string;
Expand All @@ -137,14 +136,18 @@ export function createTemplateCodegenContext(options: Pick<TemplateCodegenOption
lastGenericComment,
hasSlotElements,
blockConditions,
usedComponentCtxVars,
scopedClasses,
emptyClassOffsets,
inlayHints,
hasSlot: false,
bindingAttrLocs,
inheritedAttrVars,
templateRefs,
currentComponent: undefined as {
node: CompilerDOM.ElementNode;
ctxVar: string;
used: boolean;
} | undefined,
singleRootElType: undefined as string | undefined,
singleRootNode: undefined as CompilerDOM.ElementNode | undefined,
accessExternalVariable(name: string, offset?: number) {
Expand Down
45 changes: 22 additions & 23 deletions packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ const colonReg = /:/g;
export function* generateComponent(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
currentComponent: CompilerDOM.ElementNode | undefined
node: CompilerDOM.ElementNode
): Generator<Code> {
const startTagOffset = node.loc.start.offset + options.template.content.slice(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;
Expand All @@ -43,6 +42,12 @@ export function* generateComponent(
const var_defineComponentCtx = ctx.getInternalVariable();
const isComponentTag = node.tag.toLowerCase() === 'component';

ctx.currentComponent = {
node,
ctxVar: var_defineComponentCtx,
used: false
};

let props = node.props;
let dynamicTagInfo: {
tag: string;
Expand Down Expand Up @@ -231,16 +236,14 @@ export function* generateComponent(
);
yield `, ...__VLS_functionalComponentArgsRest(${var_functionalComponent}))${endOfLine}`;

currentComponent = node;

yield* generateFailedPropExps(options, ctx, failedPropExps);

const [refName, offset] = yield* generateVScope(options, ctx, node, props);
const isRootNode = node === ctx.singleRootNode;

if (refName || isRootNode) {
const varName = ctx.getInternalVariable();
ctx.usedComponentCtxVars.add(var_defineComponentCtx);
ctx.currentComponent.used = true;

yield `var ${varName} = {} as (Parameters<NonNullable<typeof ${var_defineComponentCtx}['expose']>>[0] | null)`;
if (node.codegenNode?.type === CompilerDOM.NodeTypes.VNODE_CALL
Expand All @@ -261,7 +264,7 @@ export function* generateComponent(

const usedComponentEventsVar = yield* generateElementEvents(options, ctx, node, var_functionalComponent, var_componentInstance, var_componentEvents);
if (usedComponentEventsVar) {
ctx.usedComponentCtxVars.add(var_defineComponentCtx);
ctx.currentComponent.used = true;
yield `let ${var_componentEmit}!: typeof ${var_defineComponentCtx}.emit${endOfLine}`;
yield `let ${var_componentEvents}!: __VLS_NormalizeEmits<typeof ${var_componentEmit}>${endOfLine}`;
}
Expand All @@ -280,13 +283,13 @@ export function* generateComponent(

const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot') as CompilerDOM.DirectiveNode;
if (slotDir) {
yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, var_defineComponentCtx);
yield* generateComponentSlot(options, ctx, node, slotDir);
}
else {
yield* generateElementChildren(options, ctx, node, currentComponent, var_defineComponentCtx);
yield* generateElementChildren(options, ctx, node);
}

if (ctx.usedComponentCtxVars.has(var_defineComponentCtx)) {
if (ctx.currentComponent.used) {
yield `var ${var_defineComponentCtx}!: __VLS_PickFunctionalComponentCtx<typeof ${var_originalComponent}, typeof ${var_componentInstance}>${endOfLine}`;
}
}
Expand All @@ -295,8 +298,6 @@ export function* generateElement(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string | undefined,
isVForChild: boolean
): Generator<Code> {
const startTagOffset = node.loc.start.offset + options.template.content.slice(node.loc.start.offset).indexOf(node.tag);
Expand Down Expand Up @@ -349,11 +350,11 @@ export function* generateElement(
}

const slotDir = node.props.find(p => p.type === CompilerDOM.NodeTypes.DIRECTIVE && p.name === 'slot') as CompilerDOM.DirectiveNode;
if (slotDir && componentCtxVar) {
yield* generateComponentSlot(options, ctx, node, slotDir, currentComponent, componentCtxVar);
if (slotDir && ctx.currentComponent) {
yield* generateComponentSlot(options, ctx, node, slotDir);
}
else {
yield* generateElementChildren(options, ctx, node, currentComponent, componentCtxVar);
yield* generateElementChildren(options, ctx, node);
}

if (
Expand Down Expand Up @@ -486,14 +487,12 @@ function* generateComponentSlot(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
slotDir: CompilerDOM.DirectiveNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string
slotDir: CompilerDOM.DirectiveNode
): Generator<Code> {
yield `{${newLine}`;
ctx.usedComponentCtxVars.add(componentCtxVar);
if (currentComponent) {
ctx.hasSlotElements.add(currentComponent);
if (ctx.currentComponent) {
ctx.currentComponent.used = true;
ctx.hasSlotElements.add(ctx.currentComponent.node);
}
const slotBlockVars: string[] = [];
yield `const {`;
Expand All @@ -517,7 +516,7 @@ function* generateComponentSlot(
`default`
);
}
yield `: __VLS_thisSlot } = ${componentCtxVar}.slots!${endOfLine}`;
yield `: __VLS_thisSlot } = ${ctx.currentComponent!.ctxVar}.slots!${endOfLine}`;

if (slotDir?.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION) {
const slotAst = createTsAst(options.ts, slotDir, `(${slotDir.exp.content}) => {}`);
Expand Down Expand Up @@ -552,7 +551,7 @@ function* generateComponentSlot(

let prev: CompilerDOM.TemplateChildNode | undefined;
for (const childNode of node.children) {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar);
yield* generateTemplateChild(options, ctx, childNode, prev);
prev = childNode;
}

Expand All @@ -564,7 +563,7 @@ function* generateComponentSlot(
isStatic = slotDir.arg.isStatic;
}
if (isStatic && slotDir && !slotDir.arg) {
yield `${componentCtxVar}.slots!['`;
yield `${ctx.currentComponent!.ctxVar}.slots!['`;
yield [
'',
'template',
Expand Down
12 changes: 5 additions & 7 deletions packages/language-core/lib/codegen/template/elementChildren.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,26 @@ import { generateTemplateChild } from './templateChild';
export function* generateElementChildren(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ElementNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string | undefined
node: CompilerDOM.ElementNode
): Generator<Code> {
yield* ctx.resetDirectiveComments('end of element children start');
let prev: CompilerDOM.TemplateChildNode | undefined;
for (const childNode of node.children) {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar);
yield* generateTemplateChild(options, ctx, childNode, prev);
prev = childNode;
}
yield* ctx.generateAutoImportCompletion();

// fix https://github.com/vuejs/language-tools/issues/932
if (
componentCtxVar
ctx.currentComponent
&& !ctx.hasSlotElements.has(node)
&& node.children.length
&& node.tagType !== CompilerDOM.ElementTypes.ELEMENT
&& node.tagType !== CompilerDOM.ElementTypes.TEMPLATE
) {
ctx.usedComponentCtxVars.add(componentCtxVar);
yield `${componentCtxVar}.slots!.`;
ctx.currentComponent.used = true;
yield `${ctx.currentComponent.ctxVar}.slots!.`;
yield* wrapWith(
node.children[0].loc.start.offset,
node.children[node.children.length - 1].loc.end.offset,
Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/lib/codegen/template/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function* generateTemplate(options: TemplateCodegenOptions): Generator<Co
ctx.addLocalVariable('$el');

if (options.template.ast) {
yield* generateTemplateChild(options, ctx, options.template.ast, undefined, undefined, undefined);
yield* generateTemplateChild(options, ctx, options.template.ast, undefined);
}

yield* generateStyleScopedClassReferences(ctx);
Expand Down
6 changes: 2 additions & 4 deletions packages/language-core/lib/codegen/template/slotOutlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import { generateInterpolation } from './interpolation';
export function* generateSlotOutlet(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.SlotOutletNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string | undefined
node: CompilerDOM.SlotOutletNode
): Generator<Code> {
const startTagOffset = node.loc.start.offset + options.template.content.slice(node.loc.start.offset).indexOf(node.tag);
const varSlot = ctx.getInternalVariable();
Expand Down Expand Up @@ -114,5 +112,5 @@ export function* generateSlotOutlet(
}
}
yield* ctx.generateAutoImportCompletion();
yield* generateElementChildren(options, ctx, node, currentComponent, componentCtxVar);
yield* generateElementChildren(options, ctx, node);
}
24 changes: 12 additions & 12 deletions packages/language-core/lib/codegen/template/templateChild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ export function* generateTemplateChild(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode | CompilerDOM.SimpleExpressionNode,
currentComponent: CompilerDOM.ElementNode | undefined,
prevNode: CompilerDOM.TemplateChildNode | undefined,
componentCtxVar: string | undefined,
isVForChild: boolean = false
): Generator<Code> {
if (prevNode?.type === CompilerDOM.NodeTypes.COMMENT) {
Expand Down Expand Up @@ -71,7 +69,7 @@ export function* generateTemplateChild(
ctx.singleRootNode = node.children[0];
}
for (const childNode of node.children) {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar);
yield* generateTemplateChild(options, ctx, childNode, prev);
prev = childNode;
}
yield* ctx.resetDirectiveComments('end of root');
Expand All @@ -80,35 +78,37 @@ export function* generateTemplateChild(
const vForNode = getVForNode(node);
const vIfNode = getVIfNode(node);
if (vForNode) {
yield* generateVFor(options, ctx, vForNode, currentComponent, componentCtxVar);
yield* generateVFor(options, ctx, vForNode);
}
else if (vIfNode) {
yield* generateVIf(options, ctx, vIfNode, currentComponent, componentCtxVar);
yield* generateVIf(options, ctx, vIfNode);
}
else {
if (node.tagType === CompilerDOM.ElementTypes.SLOT) {
yield* generateSlotOutlet(options, ctx, node, currentComponent, componentCtxVar);
yield* generateSlotOutlet(options, ctx, node);
}
else if (
node.tagType === CompilerDOM.ElementTypes.ELEMENT
|| node.tagType === CompilerDOM.ElementTypes.TEMPLATE
) {
yield* generateElement(options, ctx, node, currentComponent, componentCtxVar, isVForChild);
yield* generateElement(options, ctx, node, isVForChild);
}
else {
yield* generateComponent(options, ctx, node, currentComponent);
const { currentComponent } = ctx;
yield* generateComponent(options, ctx, node);
ctx.currentComponent = currentComponent;
}
}
}
else if (node.type === CompilerDOM.NodeTypes.TEXT_CALL) {
// {{ var }}
yield* generateTemplateChild(options, ctx, node.content, currentComponent, undefined, componentCtxVar);
yield* generateTemplateChild(options, ctx, node.content, undefined);
}
else if (node.type === CompilerDOM.NodeTypes.COMPOUND_EXPRESSION) {
// {{ ... }} {{ ... }}
for (const childNode of node.children) {
if (typeof childNode === 'object') {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, undefined, componentCtxVar);
yield* generateTemplateChild(options, ctx, childNode, undefined);
}
}
}
Expand All @@ -130,11 +130,11 @@ export function* generateTemplateChild(
}
else if (node.type === CompilerDOM.NodeTypes.IF) {
// v-if / v-else-if / v-else
yield* generateVIf(options, ctx, node, currentComponent, componentCtxVar);
yield* generateVIf(options, ctx, node);
}
else if (node.type === CompilerDOM.NodeTypes.FOR) {
// v-for
yield* generateVFor(options, ctx, node, currentComponent, componentCtxVar);
yield* generateVFor(options, ctx, node);
}
else if (node.type === CompilerDOM.NodeTypes.TEXT) {
// not needed progress
Expand Down
6 changes: 2 additions & 4 deletions packages/language-core/lib/codegen/template/vFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import { generateTemplateChild } from './templateChild';
export function* generateVFor(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.ForNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string | undefined
node: CompilerDOM.ForNode
): Generator<Code> {
const { source } = node.parseResult;
const { leftExpressionRange, leftExpressionText } = parseVForNode(node);
Expand Down Expand Up @@ -88,7 +86,7 @@ export function* generateVFor(
}
let prev: CompilerDOM.TemplateChildNode | undefined;
for (const childNode of node.children) {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar, true);
yield* generateTemplateChild(options, ctx, childNode, prev, true);
prev = childNode;
}
for (const varName of forBlockVars) {
Expand Down
6 changes: 2 additions & 4 deletions packages/language-core/lib/codegen/template/vIf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { generateTemplateChild } from './templateChild';
export function* generateVIf(
options: TemplateCodegenOptions,
ctx: TemplateCodegenContext,
node: CompilerDOM.IfNode,
currentComponent: CompilerDOM.ElementNode | undefined,
componentCtxVar: string | undefined
node: CompilerDOM.IfNode
): Generator<Code> {

let originalBlockConditionsLength = ctx.blockConditions.length;
Expand Down Expand Up @@ -61,7 +59,7 @@ export function* generateVIf(
}
let prev: CompilerDOM.TemplateChildNode | undefined;
for (const childNode of branch.children) {
yield* generateTemplateChild(options, ctx, childNode, currentComponent, prev, componentCtxVar);
yield* generateTemplateChild(options, ctx, childNode, prev);
prev = childNode;
}
yield* ctx.generateAutoImportCompletion();
Expand Down
Loading