Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(language-core): inlay hints for <component :is> and <slot :name> #4661

Merged
merged 12 commits into from
Oct 23, 2024
25 changes: 25 additions & 0 deletions packages/language-core/lib/codegen/inlayHints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type * as CompilerDOM from '@vue/compiler-dom';

export interface InlayHintInfo {
blockName: string;
offset: number;
setting: string;
label: string;
tooltip?: string;
paddingRight?: boolean;
paddingLeft?: boolean;
}

export function createVBindShorthandInlayHintInfo(loc: CompilerDOM.SourceLocation, variableName: string): InlayHintInfo {
return {
blockName: 'template',
offset: loc.end.offset,
setting: 'vue.inlayHints.vBindShorthand',
label: `="${variableName}"`,
tooltip: [
`This is a shorthand for \`${loc.source}="${variableName}"\`.`,
'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'),
};
}
2 changes: 1 addition & 1 deletion packages/language-core/lib/codegen/script/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InlayHintInfo } from '../types';
import { InlayHintInfo } from '../inlayHints';
import { getLocalTypesGenerator } from '../localTypes';
import type { ScriptCodegenOptions } from './index';

Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/lib/codegen/template/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type * as CompilerDOM from '@vue/compiler-dom';
import type { Code, VueCodeInformation } from '../../types';
import { endOfLine, newLine, wrapWith } from '../common';
import type { TemplateCodegenOptions } from './index';
import { InlayHintInfo } from '../types';
import { InlayHintInfo } from '../inlayHints';

const _codeFeatures = {
all: {
Expand Down
29 changes: 20 additions & 9 deletions packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { generateInterpolation } from './interpolation';
import { generatePropertyAccess } from './propertyAccess';
import { generateTemplateChild } from './templateChild';
import { generateObjectProperty } from './objectProperty';
import { createVBindShorthandInlayHintInfo } from '../inlayHints';
import { getNodeText } from '../../parsers/scriptSetupRanges';

const colonReg = /:/g;
Expand Down Expand Up @@ -48,18 +49,25 @@ export function* generateComponent(

let props = node.props;
let dynamicTagInfo: {
exp: string;
exp: CompilerDOM.ElementNode | CompilerDOM.ExpressionNode;
tag: string;
offsets: [number, number | undefined];
astHolder: any;
isComponentIsShorthand?: boolean;
} | undefined;

if (isComponentTag) {
for (const prop of node.props) {
if (prop.type === CompilerDOM.NodeTypes.DIRECTIVE && prop.name === 'bind' && prop.arg?.loc.source === 'is' && prop.exp) {
if (
prop.type === CompilerDOM.NodeTypes.DIRECTIVE
&& prop.name === 'bind'
&& prop.arg?.loc.source === 'is'
&& prop.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
) {
dynamicTagInfo = {
exp: prop.exp.loc.source,
exp: prop.exp,
tag: prop.exp.content,
offsets: [prop.exp.loc.start.offset, undefined],
astHolder: prop.exp.loc,
isComponentIsShorthand: prop.arg.loc.end.offset === prop.exp.loc.end.offset
};
props = props.filter(p => p !== prop);
break;
Expand All @@ -69,8 +77,8 @@ export function* generateComponent(
else if (node.tag.includes('.')) {
// namespace tag
dynamicTagInfo = {
exp: node.tag,
astHolder: node.loc,
exp: node,
tag: node.tag,
offsets: [startTagOffset, endTagOffset],
};
}
Expand Down Expand Up @@ -106,12 +114,15 @@ export function* generateComponent(
yield `]${endOfLine}`;
}
else if (dynamicTagInfo) {
if (dynamicTagInfo.isComponentIsShorthand) {
ctx.inlayHints.push(createVBindShorthandInlayHintInfo(dynamicTagInfo.exp.loc, 'is'));
}
yield `const ${var_originalComponent} = (`;
yield* generateInterpolation(
options,
ctx,
dynamicTagInfo.tag,
dynamicTagInfo.exp,
dynamicTagInfo.astHolder,
dynamicTagInfo.offsets[0],
ctx.codeFeatures.all,
'(',
Expand All @@ -122,8 +133,8 @@ export function* generateComponent(
yield* generateInterpolation(
options,
ctx,
dynamicTagInfo.tag,
dynamicTagInfo.exp,
dynamicTagInfo.astHolder,
dynamicTagInfo.offsets[1],
{
...ctx.codeFeatures.all,
Expand Down
13 changes: 2 additions & 11 deletions packages/language-core/lib/codegen/template/elementProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { generateEventArg, generateEventExpression } from './elementEvents';
import type { TemplateCodegenOptions } from './index';
import { generateInterpolation } from './interpolation';
import { generateObjectProperty } from './objectProperty';
import { createVBindShorthandInlayHintInfo } from '../inlayHints';

export function* generateElementProps(
options: TemplateCodegenOptions,
Expand Down Expand Up @@ -334,17 +335,7 @@ function* generatePropExp(
features
);
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'),
});
ctx.inlayHints.push(createVBindShorthandInlayHintInfo(prop.loc, propVariableName));
}
}
}
Expand Down
10 changes: 0 additions & 10 deletions packages/language-core/lib/codegen/template/interpolation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ export function* generateInterpolation(
): Generator<Code> {
const code = prefix + _code + suffix;
const ast = createTsAst(options.ts, astHolder, code);
const vars: {
text: string,
isShorthand: boolean,
offset: number,
}[] = [];
for (let [section, offset, type] of forEachInterpolationSegment(
options.ts,
options.destructuredPropNames,
Expand Down Expand Up @@ -70,11 +65,6 @@ export function* generateInterpolation(
yield addSuffix;
}
}
if (start !== undefined) {
for (const v of vars) {
v.offset = start + v.offset - prefix.length;
}
}
}

export function* forEachInterpolationSegment(
Expand Down
5 changes: 5 additions & 0 deletions packages/language-core/lib/codegen/template/slotOutlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { generateElementChildren } from './elementChildren';
import { generateElementProps } from './elementProps';
import type { TemplateCodegenOptions } from './index';
import { generateInterpolation } from './interpolation';
import { createVBindShorthandInlayHintInfo } from '../inlayHints';

export function* generateSlotOutlet(
options: TemplateCodegenOptions,
Expand Down Expand Up @@ -80,6 +81,10 @@ export function* generateSlotOutlet(
nameProp?.type === CompilerDOM.NodeTypes.DIRECTIVE
&& nameProp.exp?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION
) {
const isShortHand = nameProp.arg?.loc.start.offset === nameProp.exp.loc.start.offset;
if (isShortHand) {
ctx.inlayHints.push(createVBindShorthandInlayHintInfo(nameProp.exp.loc, 'name'));
}
const slotExpVar = ctx.getInternalVariable();
yield `var ${slotExpVar} = `;
yield* generateInterpolation(
Expand Down
9 changes: 0 additions & 9 deletions packages/language-core/lib/codegen/types.ts

This file was deleted.