Skip to content

Commit

Permalink
feat(language-core): support jsdoc for script setup binding variables
Browse files Browse the repository at this point in the history
close #3409
  • Loading branch information
johnsoncodehk committed May 8, 2024
1 parent 964ea64 commit d0ed952
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 22 deletions.
Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions packages/language-core/lib/codegen/script/template.ts
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
Expand Down
41 changes: 28 additions & 13 deletions 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: {
Expand Down Expand Up @@ -43,7 +44,7 @@ const _codeFeatures = {

export type TemplateCodegenContext = ReturnType<typeof createTemplateCodegenContext>;

export function createTemplateCodegenContext() {
export function createTemplateCodegenContext(scriptSetupBindingNames: TemplateCodegenOptions['scriptSetupBindingNames']) {
let ignoredError = false;
let expectErrorToken: {
errors: number;
Expand Down Expand Up @@ -80,7 +81,7 @@ export function createTemplateCodegenContext() {
},
});
const localVars = new Map<string, number>();
const accessGlobalVariables = new Map<string, Set<number>>();
const accessExternalVariables = new Map<string, Set<number>>();
const slots: {
name: string;
loc?: number;
Expand All @@ -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);
Expand Down Expand Up @@ -165,20 +166,34 @@ export function createTemplateCodegenContext() {
}
},
generateAutoImportCompletion: function* (): Generator<Code> {
const all = [...accessGlobalVariables.entries()];
const all = [...accessExternalVariables.entries()];
if (!all.some(([_, offsets]) => offsets.size)) {
return;
}
yield `// @ts-ignore${newLine}`; // #2304
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();
Expand Down
Expand Up @@ -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(
Expand Down
Expand Up @@ -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(
Expand Down
5 changes: 3 additions & 2 deletions packages/language-core/lib/codegen/template/index.ts
Expand Up @@ -15,14 +15,15 @@ export interface TemplateCodegenOptions {
template: NonNullable<Sfc['template']>;
shouldGenerateScopedClasses?: boolean;
stylesScopedClasses: Set<string>;
scriptSetupBindingNames: Set<string>;
scriptSetupImportComponentNames: Set<string>;
hasDefineSlots?: boolean;
slotsAssignName?: string;
propsAssignName?: string;
}

export function* generateTemplate(options: TemplateCodegenOptions) {
const ctx = createTemplateCodegenContext();
export function* generateTemplate(options: TemplateCodegenOptions): Generator<Code> {
const ctx = createTemplateCodegenContext(options.scriptSetupBindingNames);

let hasSlot = false;

Expand Down
4 changes: 2 additions & 2 deletions packages/language-core/lib/codegen/template/interpolation.ts
Expand Up @@ -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);
}
}
};
Expand Down
14 changes: 14 additions & 0 deletions packages/language-core/lib/plugins/vue-tsx.ts
Expand Up @@ -119,6 +119,7 @@ function createTsx(
template: _sfc.template,
shouldGenerateScopedClasses: shouldGenerateScopedClasses(),
stylesScopedClasses: stylesScopedClasses(),
scriptSetupBindingNames: scriptSetupBindingNames(),
scriptSetupImportComponentNames: scriptSetupImportComponentNames(),
hasDefineSlots: hasDefineSlots(),
slotsAssignName: slotsAssignName(),
Expand All @@ -139,6 +140,19 @@ function createTsx(
};
});
const hasDefineSlots = computed(() => !!scriptSetupRanges()?.slots.define);
const scriptSetupBindingNames = computed<Set<string>>(oldNames => {
const newNames = new Set<string>();
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<Set<string>>(oldNames => {
const newNames = scriptSetupRanges()?.importComponentNames ?? new Set();
if (newNames && oldNames && twoSetsEqual(newNames, oldNames)) {
Expand Down

0 comments on commit d0ed952

Please sign in to comment.