diff --git a/packages/language-core/lib/codegen/inlayHints.ts b/packages/language-core/lib/codegen/inlayHints.ts new file mode 100644 index 0000000000..10b0946753 --- /dev/null +++ b/packages/language-core/lib/codegen/inlayHints.ts @@ -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'), + }; +} diff --git a/packages/language-core/lib/codegen/script/context.ts b/packages/language-core/lib/codegen/script/context.ts index 60d30f82ce..a67d018de2 100644 --- a/packages/language-core/lib/codegen/script/context.ts +++ b/packages/language-core/lib/codegen/script/context.ts @@ -1,4 +1,4 @@ -import { InlayHintInfo } from '../types'; +import { InlayHintInfo } from '../inlayHints'; import { getLocalTypesGenerator } from '../localTypes'; import type { ScriptCodegenOptions } from './index'; diff --git a/packages/language-core/lib/codegen/template/context.ts b/packages/language-core/lib/codegen/template/context.ts index b4da54a6e8..c5abab54e1 100644 --- a/packages/language-core/lib/codegen/template/context.ts +++ b/packages/language-core/lib/codegen/template/context.ts @@ -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: { diff --git a/packages/language-core/lib/codegen/template/element.ts b/packages/language-core/lib/codegen/template/element.ts index 9976f15b5d..ec8721835e 100644 --- a/packages/language-core/lib/codegen/template/element.ts +++ b/packages/language-core/lib/codegen/template/element.ts @@ -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; @@ -48,16 +49,24 @@ export function* generateComponent( let props = node.props; let dynamicTagInfo: { - exp: string; + tag: string; offsets: [number, number | undefined]; - astHolder: any; + astHolder: CompilerDOM.SourceLocation; } | 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 + ) { + if (prop.arg.loc.end.offset === prop.exp.loc.end.offset) { + ctx.inlayHints.push(createVBindShorthandInlayHintInfo(prop.exp.loc, 'is')); + } dynamicTagInfo = { - exp: prop.exp.loc.source, + tag: prop.exp.content, offsets: [prop.exp.loc.start.offset, undefined], astHolder: prop.exp.loc, }; @@ -69,9 +78,9 @@ export function* generateComponent( else if (node.tag.includes('.')) { // namespace tag dynamicTagInfo = { - exp: node.tag, - astHolder: node.loc, + tag: node.tag, offsets: [startTagOffset, endTagOffset], + astHolder: node.loc, }; } @@ -110,7 +119,7 @@ export function* generateComponent( yield* generateInterpolation( options, ctx, - dynamicTagInfo.exp, + dynamicTagInfo.tag, dynamicTagInfo.astHolder, dynamicTagInfo.offsets[0], ctx.codeFeatures.all, @@ -122,7 +131,7 @@ export function* generateComponent( yield* generateInterpolation( options, ctx, - dynamicTagInfo.exp, + dynamicTagInfo.tag, dynamicTagInfo.astHolder, dynamicTagInfo.offsets[1], { diff --git a/packages/language-core/lib/codegen/template/elementProps.ts b/packages/language-core/lib/codegen/template/elementProps.ts index 809f42d225..dfaf3cbac2 100644 --- a/packages/language-core/lib/codegen/template/elementProps.ts +++ b/packages/language-core/lib/codegen/template/elementProps.ts @@ -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, @@ -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)); } } } diff --git a/packages/language-core/lib/codegen/template/interpolation.ts b/packages/language-core/lib/codegen/template/interpolation.ts index 1707b7f3f2..8880aa879c 100644 --- a/packages/language-core/lib/codegen/template/interpolation.ts +++ b/packages/language-core/lib/codegen/template/interpolation.ts @@ -18,11 +18,6 @@ export function* generateInterpolation( ): Generator { 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, @@ -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( diff --git a/packages/language-core/lib/codegen/template/slotOutlet.ts b/packages/language-core/lib/codegen/template/slotOutlet.ts index c42a086074..021d51faf7 100644 --- a/packages/language-core/lib/codegen/template/slotOutlet.ts +++ b/packages/language-core/lib/codegen/template/slotOutlet.ts @@ -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, @@ -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( diff --git a/packages/language-core/lib/codegen/types.ts b/packages/language-core/lib/codegen/types.ts deleted file mode 100644 index 964bb46076..0000000000 --- a/packages/language-core/lib/codegen/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface InlayHintInfo { - blockName: string; - offset: number; - setting: string; - label: string; - tooltip?: string; - paddingRight?: boolean; - paddingLeft?: boolean; -}