From d0ed952b245977f16d978d40cee500a34d925f57 Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Wed, 8 May 2024 20:07:23 +0800 Subject: [PATCH] feat(language-core): support jsdoc for script setup binding variables close #3409 --- .../lib/codegen/script/internalComponent.ts | 2 +- .../lib/codegen/script/template.ts | 4 +- .../lib/codegen/template/context.ts | 41 +++++++++++++------ .../lib/codegen/template/elementDirectives.ts | 2 +- .../lib/codegen/template/elementProps.ts | 2 +- .../lib/codegen/template/index.ts | 5 ++- .../lib/codegen/template/interpolation.ts | 4 +- packages/language-core/lib/plugins/vue-tsx.ts | 14 +++++++ 8 files changed, 52 insertions(+), 22 deletions(-) diff --git a/packages/language-core/lib/codegen/script/internalComponent.ts b/packages/language-core/lib/codegen/script/internalComponent.ts index c5a0d600e..b0121d613 100644 --- a/packages/language-core/lib/codegen/script/internalComponent.ts +++ b/packages/language-core/lib/codegen/script/internalComponent.ts @@ -28,7 +28,7 @@ export function* generateInternalComponent( ]) { for (const expose of bindings) { 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; } const templateOffset = options.getGeneratedLength(); diff --git a/packages/language-core/lib/codegen/script/template.ts b/packages/language-core/lib/codegen/script/template.ts index 1acdc6653..a5fe917c6 100644 --- a/packages/language-core/lib/codegen/script/template.ts +++ b/packages/language-core/lib/codegen/script/template.ts @@ -17,13 +17,13 @@ export function* generateTemplate( ctx.generatedTemplate = true; if (!options.vueCompilerOptions.skipTemplateCodegen) { - const templateCodegenCtx = createTemplateCodegenContext(); if (isClassComponent) { yield `__VLS_template() {${newLine}`; } else { yield `function __VLS_template() {${newLine}`; } + const templateCodegenCtx = createTemplateCodegenContext(new Set()); yield* generateCtx(options, ctx, isClassComponent); yield* generateTemplateContext(options, templateCodegenCtx); yield* generateExportOptions(options); @@ -255,7 +255,7 @@ export function getTemplateUsageVars(options: ScriptCodegenOptions, ctx: ScriptC usageVars.add(component.split('.')[0]); } } - for (const [varName] of options.templateCodegen.ctx.accessGlobalVariables) { + for (const [varName] of options.templateCodegen.ctx.accessExternalVariables) { usageVars.add(varName); } } diff --git a/packages/language-core/lib/codegen/template/context.ts b/packages/language-core/lib/codegen/template/context.ts index e8673496f..f607956d2 100644 --- a/packages/language-core/lib/codegen/template/context.ts +++ b/packages/language-core/lib/codegen/template/context.ts @@ -1,6 +1,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'; const _codeFeatures = { all: { @@ -43,7 +44,7 @@ const _codeFeatures = { export type TemplateCodegenContext = ReturnType; -export function createTemplateCodegenContext() { +export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCodegenOptions['scriptSetupBindingNames']) { let ignoredError = false; let expectErrorToken: { errors: number; @@ -80,7 +81,7 @@ export function createTemplateCodegenContext() { }, }); const localVars = new Map(); - const accessGlobalVariables = new Map>(); + const accessExternalVariables = new Map>(); const slots: { name: string; loc?: number; @@ -101,15 +102,15 @@ export function createTemplateCodegenContext() { slots, dynamicSlots, codeFeatures, - accessGlobalVariables, + accessExternalVariables, hasSlotElements, blockConditions, usedComponentCtxVars, scopedClasses, - accessGlobalVariable(name: string, offset?: number) { - let arr = accessGlobalVariables.get(name); + accessExternalVariable(name: string, offset?: number) { + let arr = accessExternalVariables.get(name); if (!arr) { - accessGlobalVariables.set(name, arr = new Set()); + accessExternalVariables.set(name, arr = new Set()); } if (offset !== undefined) { arr.add(offset); @@ -165,7 +166,7 @@ export function createTemplateCodegenContext() { } }, generateAutoImportCompletion: function* (): Generator { - const all = [...accessGlobalVariables.entries()]; + const all = [...accessExternalVariables.entries()]; if (!all.some(([_, offsets]) => offsets.size)) { return; } @@ -173,12 +174,26 @@ export function createTemplateCodegenContext() { yield `[`; for (const [varName, offsets] of all) { 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 `,`; } offsets.clear(); diff --git a/packages/language-core/lib/codegen/template/elementDirectives.ts b/packages/language-core/lib/codegen/template/elementDirectives.ts index e70dbab99..dc8c93857 100644 --- a/packages/language-core/lib/codegen/template/elementDirectives.ts +++ b/packages/language-core/lib/codegen/template/elementDirectives.ts @@ -23,7 +23,7 @@ export function* generateElementDirectives( && prop.name !== 'scope' && prop.name !== 'data' ) { - ctx.accessGlobalVariable(camelize('v-' + prop.name), prop.loc.start.offset); + ctx.accessExternalVariable(camelize('v-' + prop.name), prop.loc.start.offset); if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && !prop.arg.isStatic) { yield* generateInterpolation( diff --git a/packages/language-core/lib/codegen/template/elementProps.ts b/packages/language-core/lib/codegen/template/elementProps.ts index 2ed145459..80f5346a4 100644 --- a/packages/language-core/lib/codegen/template/elementProps.ts +++ b/packages/language-core/lib/codegen/template/elementProps.ts @@ -284,7 +284,7 @@ function* genereatePropExp( if (variableNameRegex.test(propVariableName)) { if (!ctx.hasLocalVariable(propVariableName)) { - ctx.accessGlobalVariable(propVariableName, exp.loc.start.offset); + ctx.accessExternalVariable(propVariableName, exp.loc.start.offset); yield `__VLS_ctx.`; } yield* generateCamelized( diff --git a/packages/language-core/lib/codegen/template/index.ts b/packages/language-core/lib/codegen/template/index.ts index 0e655f6c2..90e1509b8 100644 --- a/packages/language-core/lib/codegen/template/index.ts +++ b/packages/language-core/lib/codegen/template/index.ts @@ -15,14 +15,15 @@ export interface TemplateCodegenOptions { template: NonNullable; shouldGenerateScopedClasses?: boolean; stylesScopedClasses: Set; + scriptSetupBindingNames: Set; scriptSetupImportComponentNames: Set; hasDefineSlots?: boolean; slotsAssignName?: string; propsAssignName?: string; } -export function* generateTemplate(options: TemplateCodegenOptions) { - const ctx = createTemplateCodegenContext(); +export function* generateTemplate(options: TemplateCodegenOptions): Generator { + const ctx = createTemplateCodegenContext(options.scriptSetupBindingNames); let hasSlot = false; diff --git a/packages/language-core/lib/codegen/template/interpolation.ts b/packages/language-core/lib/codegen/template/interpolation.ts index ed17f1f95..3571c93cc 100644 --- a/packages/language-core/lib/codegen/template/interpolation.ts +++ b/packages/language-core/lib/codegen/template/interpolation.ts @@ -100,10 +100,10 @@ export function* forEachInterpolationSegment( offset: getStartEnd(ts, id, ast).start, }); if (offset !== undefined) { - ctx.accessGlobalVariable(text, offset + getStartEnd(ts, id, ast).start); + ctx.accessExternalVariable(text, offset + getStartEnd(ts, id, ast).start); } else { - ctx.accessGlobalVariable(text); + ctx.accessExternalVariable(text); } } }; diff --git a/packages/language-core/lib/plugins/vue-tsx.ts b/packages/language-core/lib/plugins/vue-tsx.ts index cf367a73d..91a004f43 100644 --- a/packages/language-core/lib/plugins/vue-tsx.ts +++ b/packages/language-core/lib/plugins/vue-tsx.ts @@ -119,6 +119,7 @@ function createTsx( template: _sfc.template, shouldGenerateScopedClasses: shouldGenerateScopedClasses(), stylesScopedClasses: stylesScopedClasses(), + scriptSetupBindingNames: scriptSetupBindingNames(), scriptSetupImportComponentNames: scriptSetupImportComponentNames(), hasDefineSlots: hasDefineSlots(), slotsAssignName: slotsAssignName(), @@ -139,6 +140,19 @@ function createTsx( }; }); const hasDefineSlots = computed(() => !!scriptSetupRanges()?.slots.define); + const scriptSetupBindingNames = 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 = computed>(oldNames => { const newNames = scriptSetupRanges()?.importComponentNames ?? new Set(); if (newNames && oldNames && twoSetsEqual(newNames, oldNames)) {