Skip to content

Commit d0ed952

Browse files
committed
feat(language-core): support jsdoc for script setup binding variables
close #3409
1 parent 964ea64 commit d0ed952

File tree

8 files changed

+52
-22
lines changed

8 files changed

+52
-22
lines changed

packages/language-core/lib/codegen/script/internalComponent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function* generateInternalComponent(
2828
]) {
2929
for (const expose of bindings) {
3030
const varName = content.substring(expose.start, expose.end);
31-
if (!templateUsageVars.has(varName) && !templateCodegenCtx.accessGlobalVariables.has(varName)) {
31+
if (!templateUsageVars.has(varName) && !templateCodegenCtx.accessExternalVariables.has(varName)) {
3232
continue;
3333
}
3434
const templateOffset = options.getGeneratedLength();

packages/language-core/lib/codegen/script/template.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ export function* generateTemplate(
1717
ctx.generatedTemplate = true;
1818

1919
if (!options.vueCompilerOptions.skipTemplateCodegen) {
20-
const templateCodegenCtx = createTemplateCodegenContext();
2120
if (isClassComponent) {
2221
yield `__VLS_template() {${newLine}`;
2322
}
2423
else {
2524
yield `function __VLS_template() {${newLine}`;
2625
}
26+
const templateCodegenCtx = createTemplateCodegenContext(new Set());
2727
yield* generateCtx(options, ctx, isClassComponent);
2828
yield* generateTemplateContext(options, templateCodegenCtx);
2929
yield* generateExportOptions(options);
@@ -255,7 +255,7 @@ export function getTemplateUsageVars(options: ScriptCodegenOptions, ctx: ScriptC
255255
usageVars.add(component.split('.')[0]);
256256
}
257257
}
258-
for (const [varName] of options.templateCodegen.ctx.accessGlobalVariables) {
258+
for (const [varName] of options.templateCodegen.ctx.accessExternalVariables) {
259259
usageVars.add(varName);
260260
}
261261
}

packages/language-core/lib/codegen/template/context.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type * as CompilerDOM from '@vue/compiler-dom';
22
import type { Code, VueCodeInformation } from '../../types';
33
import { endOfLine, newLine, wrapWith } from '../common';
4+
import type { TemplateCodegenOptions } from './index';
45

56
const _codeFeatures = {
67
all: {
@@ -43,7 +44,7 @@ const _codeFeatures = {
4344

4445
export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>;
4546

46-
export function createTemplateCodegenContext() {
47+
export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCodegenOptions['scriptSetupBindingNames']) {
4748
let ignoredError = false;
4849
let expectErrorToken: {
4950
errors: number;
@@ -80,7 +81,7 @@ export function createTemplateCodegenContext() {
8081
},
8182
});
8283
const localVars = new Map<string, number>();
83-
const accessGlobalVariables = new Map<string, Set<number>>();
84+
const accessExternalVariables = new Map<string, Set<number>>();
8485
const slots: {
8586
name: string;
8687
loc?: number;
@@ -101,15 +102,15 @@ export function createTemplateCodegenContext() {
101102
slots,
102103
dynamicSlots,
103104
codeFeatures,
104-
accessGlobalVariables,
105+
accessExternalVariables,
105106
hasSlotElements,
106107
blockConditions,
107108
usedComponentCtxVars,
108109
scopedClasses,
109-
accessGlobalVariable(name: string, offset?: number) {
110-
let arr = accessGlobalVariables.get(name);
110+
accessExternalVariable(name: string, offset?: number) {
111+
let arr = accessExternalVariables.get(name);
111112
if (!arr) {
112-
accessGlobalVariables.set(name, arr = new Set());
113+
accessExternalVariables.set(name, arr = new Set());
113114
}
114115
if (offset !== undefined) {
115116
arr.add(offset);
@@ -165,20 +166,34 @@ export function createTemplateCodegenContext() {
165166
}
166167
},
167168
generateAutoImportCompletion: function* (): Generator<Code> {
168-
const all = [...accessGlobalVariables.entries()];
169+
const all = [...accessExternalVariables.entries()];
169170
if (!all.some(([_, offsets]) => offsets.size)) {
170171
return;
171172
}
172173
yield `// @ts-ignore${newLine}`; // #2304
173174
yield `[`;
174175
for (const [varName, offsets] of all) {
175176
for (const offset of offsets) {
176-
yield [
177-
varName,
178-
'template',
179-
offset,
180-
codeFeatures.additionalCompletion,
181-
];
177+
if (scriptSetupBindingNames.has(varName)) {
178+
// #3409
179+
yield [
180+
varName,
181+
'template',
182+
offset,
183+
{
184+
...codeFeatures.additionalCompletion,
185+
...codeFeatures.withoutHighlightAndCompletionAndNavigation,
186+
},
187+
];
188+
}
189+
else {
190+
yield [
191+
varName,
192+
'template',
193+
offset,
194+
codeFeatures.additionalCompletion,
195+
];
196+
}
182197
yield `,`;
183198
}
184199
offsets.clear();

packages/language-core/lib/codegen/template/elementDirectives.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function* generateElementDirectives(
2323
&& prop.name !== 'scope'
2424
&& prop.name !== 'data'
2525
) {
26-
ctx.accessGlobalVariable(camelize('v-' + prop.name), prop.loc.start.offset);
26+
ctx.accessExternalVariable(camelize('v-' + prop.name), prop.loc.start.offset);
2727

2828
if (prop.arg?.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION && !prop.arg.isStatic) {
2929
yield* generateInterpolation(

packages/language-core/lib/codegen/template/elementProps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ function* genereatePropExp(
284284

285285
if (variableNameRegex.test(propVariableName)) {
286286
if (!ctx.hasLocalVariable(propVariableName)) {
287-
ctx.accessGlobalVariable(propVariableName, exp.loc.start.offset);
287+
ctx.accessExternalVariable(propVariableName, exp.loc.start.offset);
288288
yield `__VLS_ctx.`;
289289
}
290290
yield* generateCamelized(

packages/language-core/lib/codegen/template/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ export interface TemplateCodegenOptions {
1515
template: NonNullable<Sfc['template']>;
1616
shouldGenerateScopedClasses?: boolean;
1717
stylesScopedClasses: Set<string>;
18+
scriptSetupBindingNames: Set<string>;
1819
scriptSetupImportComponentNames: Set<string>;
1920
hasDefineSlots?: boolean;
2021
slotsAssignName?: string;
2122
propsAssignName?: string;
2223
}
2324

24-
export function* generateTemplate(options: TemplateCodegenOptions) {
25-
const ctx = createTemplateCodegenContext();
25+
export function* generateTemplate(options: TemplateCodegenOptions): Generator<Code> {
26+
const ctx = createTemplateCodegenContext(options.scriptSetupBindingNames);
2627

2728
let hasSlot = false;
2829

packages/language-core/lib/codegen/template/interpolation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ export function* forEachInterpolationSegment(
100100
offset: getStartEnd(ts, id, ast).start,
101101
});
102102
if (offset !== undefined) {
103-
ctx.accessGlobalVariable(text, offset + getStartEnd(ts, id, ast).start);
103+
ctx.accessExternalVariable(text, offset + getStartEnd(ts, id, ast).start);
104104
}
105105
else {
106-
ctx.accessGlobalVariable(text);
106+
ctx.accessExternalVariable(text);
107107
}
108108
}
109109
};

packages/language-core/lib/plugins/vue-tsx.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ function createTsx(
119119
template: _sfc.template,
120120
shouldGenerateScopedClasses: shouldGenerateScopedClasses(),
121121
stylesScopedClasses: stylesScopedClasses(),
122+
scriptSetupBindingNames: scriptSetupBindingNames(),
122123
scriptSetupImportComponentNames: scriptSetupImportComponentNames(),
123124
hasDefineSlots: hasDefineSlots(),
124125
slotsAssignName: slotsAssignName(),
@@ -139,6 +140,19 @@ function createTsx(
139140
};
140141
});
141142
const hasDefineSlots = computed(() => !!scriptSetupRanges()?.slots.define);
143+
const scriptSetupBindingNames = computed<Set<string>>(oldNames => {
144+
const newNames = new Set<string>();
145+
const bindings = scriptSetupRanges()?.bindings;
146+
if (_sfc.scriptSetup && bindings) {
147+
for (const binding of bindings) {
148+
newNames.add(_sfc.scriptSetup?.content.substring(binding.start, binding.end));
149+
}
150+
}
151+
if (newNames && oldNames && twoSetsEqual(newNames, oldNames)) {
152+
return oldNames;
153+
}
154+
return newNames;
155+
});
142156
const scriptSetupImportComponentNames = computed<Set<string>>(oldNames => {
143157
const newNames = scriptSetupRanges()?.importComponentNames ?? new Set();
144158
if (newNames && oldNames && twoSetsEqual(newNames, oldNames)) {

0 commit comments

Comments
 (0)