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
Prev Previous commit
Next Next commit
fix: inlay hints for <component :is> and <slot :name>
Co-authored-by: so1ve <i@mk1.io>
  • Loading branch information
KazariEX and so1ve committed Aug 7, 2024
commit 05f4d58bfeff5d87cbef603cc1605fbb1ffaaf7b
30 changes: 21 additions & 9 deletions packages/language-core/lib/codegen/template/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { generateInterpolation } from './interpolation';
import { generatePropertyAccess } from './propertyAccess';
import { generateTemplateChild } from './templateChild';
import { generateObjectProperty } from './objectProperty';
import { generateVBindShorthandInlayHint } from './vBindShorthand';

const colonReg = /:/g;

Expand Down Expand Up @@ -46,18 +47,25 @@ export function* generateComponent(

let props = node.props;
let dynamicTagInfo: {
exp: string;
exp: CompilerDOM.ElementNode | CompilerDOM.ExpressionNode;
tag: string;
offset: number;
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,
offset: prop.exp.loc.start.offset,
astHolder: prop.exp.loc,
isComponentIsShorthand: prop.arg.loc.end.offset === prop.exp.loc.end.offset
};
props = props.filter(p => p !== prop);
break;
Expand All @@ -67,8 +75,8 @@ export function* generateComponent(
else if (node.tag.includes('.')) {
// namespace tag
dynamicTagInfo = {
exp: node.tag,
astHolder: node.loc,
exp: node,
tag: node.tag,
offset: startTagOffset,
};
}
Expand Down Expand Up @@ -108,12 +116,16 @@ export function* generateComponent(
yield* generateInterpolation(
options,
ctx,
dynamicTagInfo.tag,
dynamicTagInfo.exp,
dynamicTagInfo.astHolder,
dynamicTagInfo.offset,
ctx.codeFeatures.all,
'(',
')'
')',
dynamicTagInfo.isComponentIsShorthand ? [[
generateVBindShorthandInlayHint(dynamicTagInfo.exp.loc, 'is'),
dynamicTagInfo.exp.loc.end.offset
]] : undefined
);
yield endOfLine;
}
Expand Down
18 changes: 2 additions & 16 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 { generateVBindShorthandInlayHint } from './vBindShorthand';

export function* generateElementProps(
options: TemplateCodegenOptions,
Expand Down Expand Up @@ -297,22 +298,7 @@ function* genereatePropExp(
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'),
},
} as VueCodeInformation,
];
yield generateVBindShorthandInlayHint(exp.loc, propVariableName);
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion 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 { generateVBindShorthandInlayHint } from './vBindShorthand';

export function* generateSlotOutlet(
options: TemplateCodegenOptions,
Expand Down Expand Up @@ -80,6 +81,7 @@ 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;
const slotExpVar = ctx.getInternalVariable();
yield `var ${slotExpVar} = `;
yield* generateInterpolation(
Expand All @@ -90,7 +92,11 @@ export function* generateSlotOutlet(
nameProp.exp.loc.start.offset,
ctx.codeFeatures.all,
'(',
')'
')',
isShortHand ? [[
generateVBindShorthandInlayHint(nameProp.exp.loc, 'name'),
nameProp.exp.loc.end.offset
]] : undefined
);
yield ` as const${endOfLine}`;
ctx.dynamicSlots.push({
Expand Down
21 changes: 21 additions & 0 deletions packages/language-core/lib/codegen/template/vBindShorthand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type * as CompilerDOM from '@vue/compiler-dom';
import type { Code } from "../../types";

export function generateVBindShorthandInlayHint(loc: CompilerDOM.SourceLocation, variableName: string): Code {
return [
'',
'template',
loc.end.offset,
{
__hint: {
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'),
},
},
];
};
4 changes: 2 additions & 2 deletions packages/language-service/tests/inlayHint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ function readFiles(dir: string) {
return filesText;
}

const inlayHintReg = /(\^*)inlayHint:\s*"(.+)"/g;
const inlayHintReg = /(\^*)inlayHint:\s*(['"])(.+)\2/g;

function findActions(text: string) {

return [...text.matchAll(inlayHintReg)].map(flag => {

const offset = flag.index!;
const label = flag[2];
const label = flag[3];

return {
offset,
Expand Down
1 change: 1 addition & 0 deletions packages/language-service/tests/utils/createTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function createTester(rootUri: URI) {
'vue.inlayHints.missingProps': true,
'vue.inlayHints.optionsWrapper': true,
'vue.inlayHints.inlineHandlerLeading': true,
'vue.inlayHints.vBindShorthand': true,
};
let currentVSCodeSettings: any;
const language = createLanguage(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
let foo = 0;
let name = '';
let is = () => {};
</script>

<template>
<div :foo></div>
<!-- ^inlayHint: '="foo"' -->
<slot :foo></slot>
<!-- ^inlayHint: '="foo"' -->
<slot :name></slot>
<!-- ^inlayHint: '="name"' -->
<component :is></component>
<!-- ^inlayHint: '="is"' -->
</template>