Skip to content
1 change: 1 addition & 0 deletions packages/language-core/lib/codegen/names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export const InternalProps = '__VLS_InternalProps';
export const Emit = '__VLS_Emit';
export const Bindings = '__VLS_Bindings';
export const PublicProps = '__VLS_PublicProps';
export const StyleModules = '__VLS_StyleModules';

export const PROPS_FALLBACK = '__VLS_PROPS_FALLBACK';
8 changes: 0 additions & 8 deletions packages/language-core/lib/codegen/script/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ export function createScriptCodegenContext(options: ScriptCodegenOptions) {

return {
generatedTypes: new Set<string>(),
bindingNames: new Set([
...options.scriptRanges?.bindings.map(
({ range }) => options.script!.content.slice(range.start, range.end),
) ?? [],
...options.scriptSetupRanges?.bindings.map(
({ range }) => options.scriptSetup!.content.slice(range.start, range.end),
) ?? [],
]),
localTypes,
inlayHints,
};
Expand Down
6 changes: 2 additions & 4 deletions packages/language-core/lib/codegen/script/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ export interface ScriptCodegenOptions {
vueCompilerOptions: VueCompilerOptions;
script: Sfc['script'];
scriptSetup: Sfc['scriptSetup'];
styles: Sfc['styles'];
fileName: string;
lang: string;
scriptRanges: ScriptRanges | undefined;
scriptSetupRanges: ScriptSetupRanges | undefined;
templateComponents: string[];
templateStartTagOffset: number | undefined;
// TODO: remove this for better increment ality
templateCodegen: TemplateCodegenContext & { codes: Code[] } | undefined;
destructuredPropNames: Set<string>;
templateRefNames: Set<string>;
styleCodegen: TemplateCodegenContext & { codes: Code[] } | undefined;
setupBindingNames: Set<string>;
}

export { generate as generateScript };
Expand Down
16 changes: 8 additions & 8 deletions packages/language-core/lib/codegen/script/scriptSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,13 @@ export function* generateSetupFunction(
yield `(`;
}),
);
const type = options.styleCodegen?.generatedTypes.has(names.StyleModules)
? names.StyleModules
: `{}`;
if (arg) {
transforms.push(
insert(callExp.end, function*() {
yield ` as Omit<__VLS_StyleModules, '$style'>[`;
yield ` as Omit<${type}, '$style'>[`;
yield* generateSfcBlockSection(scriptSetup, arg.start, arg.end, codeFeatures.withoutSemantic);
yield `])`;
}),
Expand All @@ -206,7 +209,7 @@ export function* generateSetupFunction(
else {
transforms.push(
insert(callExp.end, function*() {
yield ` as __VLS_StyleModules[`;
yield ` as ${type}[`;
const token = yield* startBoundary(scriptSetup.name, exp.start, codeFeatures.verification);
yield `'$style'`;
yield endBoundary(token, exp.end);
Expand Down Expand Up @@ -282,7 +285,7 @@ export function* generateSetupFunction(
(start, end) =>
generateSfcBlockSection(scriptSetup, start, end, codeFeatures.all, end === scriptSetup.content.length),
);
yield* generateMacros(options, ctx);
yield* generateMacros(options);
yield* generateModels(scriptSetup, scriptSetupRanges);
yield* generatePublicProps(options, ctx, scriptSetup, scriptSetupRanges);
yield* body;
Expand All @@ -303,15 +306,12 @@ export function* generateSetupFunction(
}
}

function* generateMacros(
options: ScriptCodegenOptions,
ctx: ScriptCodegenContext,
): Generator<Code> {
function* generateMacros(options: ScriptCodegenOptions): Generator<Code> {
if (options.vueCompilerOptions.target >= 3.3) {
yield `// @ts-ignore${newLine}`;
yield `declare const { `;
for (const macro of Object.keys(options.vueCompilerOptions.macros)) {
if (!ctx.bindingNames.has(macro)) {
if (!options.setupBindingNames.has(macro)) {
yield `${macro}, `;
}
}
Expand Down
71 changes: 20 additions & 51 deletions packages/language-core/lib/codegen/script/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ import * as path from 'path-browserify';
import type { Code } from '../../types';
import { codeFeatures } from '../codeFeatures';
import * as names from '../names';
import { generateStyleModules } from '../style/modules';
import { generateStyleScopedClasses } from '../style/scopedClasses';
import { createTemplateCodegenContext, type TemplateCodegenContext } from '../template/context';
import { generateInterpolation } from '../template/interpolation';
import { endOfLine, generateSfcBlockSection, newLine } from '../utils';
import { generateSpreadMerge } from '../utils/merge';
import type { ScriptCodegenContext } from './context';
Expand All @@ -17,19 +13,14 @@ export function* generateTemplate(
ctx: ScriptCodegenContext,
): Generator<Code> {
yield* generateSelf(options);
yield* generateBindings(options, ctx);
yield* generateTemplateCtx(options, ctx);
yield* generateTemplateComponents(options);
yield* generateTemplateDirectives(options);

const templateCodegenCtx = createTemplateCodegenContext({
scriptSetupBindingNames: new Set(),
});

yield* generateStyleScopedClasses(options);
yield* generateStyleModules(options);
yield* generateCssVars(options, templateCodegenCtx);
yield* generateBindings(options, ctx, templateCodegenCtx);

if (options.styleCodegen) {
yield* options.styleCodegen.codes;
}
if (options.templateCodegen) {
yield* options.templateCodegen.codes;
}
Expand All @@ -54,7 +45,7 @@ function* generateSelf({ script, scriptRanges, vueCompilerOptions, fileName }: S
}

function* generateTemplateCtx(
{ vueCompilerOptions, script, scriptRanges, styles, scriptSetupRanges, fileName }: ScriptCodegenOptions,
{ vueCompilerOptions, script, scriptRanges, styleCodegen, scriptSetupRanges, fileName }: ScriptCodegenOptions,
ctx: ScriptCodegenContext,
): Generator<Code> {
const exps: Iterable<Code>[] = [];
Expand All @@ -70,8 +61,8 @@ function* generateTemplateCtx(
else {
exps.push([`{} as import('${vueCompilerOptions.lib}').ComponentPublicInstance`]);
}
if (styles.some(style => style.module)) {
exps.push([`{} as __VLS_StyleModules`]);
if (styleCodegen?.generatedTypes.has(names.StyleModules)) {
exps.push([`{} as ${names.StyleModules}`]);
}

if (scriptSetupRanges?.defineEmits) {
Expand Down Expand Up @@ -109,7 +100,7 @@ function* generateTemplateCtx(
exps.push([`{} as ${names.InternalProps}`]);
}

if (scriptSetupRanges && ctx.bindingNames.size) {
if (ctx.generatedTypes.has(names.Bindings)) {
exps.push([`{} as ${names.Bindings}`]);
}

Expand Down Expand Up @@ -158,53 +149,31 @@ function* generateTemplateDirectives(options: ScriptCodegenOptions): Generator<C
yield `let ${names.directives}!: __VLS_LocalDirectives & __VLS_GlobalDirectives${endOfLine}`;
}

function* generateCssVars(
options: ScriptCodegenOptions,
ctx: TemplateCodegenContext,
): Generator<Code> {
for (const style of options.styles) {
for (const binding of style.bindings) {
yield* generateInterpolation(
options,
ctx,
style,
codeFeatures.all,
binding.text,
binding.offset,
`(`,
`)`,
);
yield endOfLine;
}
}
}

function* generateBindings(
options: ScriptCodegenOptions,
{ templateComponents, templateCodegen, styleCodegen, setupBindingNames }: ScriptCodegenOptions,
ctx: ScriptCodegenContext,
templateCodegenCtx: TemplateCodegenContext,
): Generator<Code> {
if (!options.scriptSetup || !ctx.bindingNames.size) {
if (!setupBindingNames.size) {
return;
}
ctx.generatedTypes.add(names.Bindings);

const usageVars = new Set([
...options.templateComponents.flatMap(c => [camelize(c), capitalize(camelize(c))]),
...options.templateCodegen?.accessExternalVariables.keys() ?? [],
...templateCodegenCtx.accessExternalVariables.keys(),
const usedVars = new Set([
...templateComponents.flatMap(c => [camelize(c), capitalize(camelize(c))]),
...templateCodegen?.accessExternalVariables.keys() ?? [],
...styleCodegen?.accessExternalVariables.keys() ?? [],
]);

yield `type ${names.Bindings} = __VLS_ProxyRefs<{${newLine}`;
for (const varName of ctx.bindingNames) {
if (!usageVars.has(varName)) {
for (const bindingName of setupBindingNames) {
if (!usedVars.has(bindingName)) {
continue;
}

const token = Symbol(varName.length);
const token = Symbol(bindingName.length);
yield ['', undefined, 0, { __linkedToken: token }];
yield `${varName}: typeof `;
yield `${bindingName}: typeof `;
yield ['', undefined, 0, { __linkedToken: token }];
yield varName;
yield bindingName;
yield endOfLine;
}
yield `}>${endOfLine}`;
Expand Down
50 changes: 50 additions & 0 deletions packages/language-core/lib/codegen/style/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { Code, Sfc, VueCompilerOptions } from '../../types';
import { codeFeatures } from '../codeFeatures';
import { generateStyleModules } from '../style/modules';
import { generateStyleScopedClasses } from '../style/scopedClasses';
import { createTemplateCodegenContext, type TemplateCodegenContext } from '../template/context';
import { generateInterpolation } from '../template/interpolation';
import { endOfLine } from '../utils';

export interface StyleCodegenOptions {
ts: typeof import('typescript');
vueCompilerOptions: VueCompilerOptions;
styles: Sfc['styles'];
templateRefNames: Set<string>;
directAccessNames: Set<string>;
setupBindingNames: Set<string>;
}

export { generate as generateStyle };

function* generate(options: StyleCodegenOptions) {
const ctx = createTemplateCodegenContext(options.setupBindingNames);
const endScope = ctx.startScope();
ctx.declare(...options.directAccessNames);
yield* generateStyleScopedClasses(options);
yield* generateStyleModules(options, ctx);
yield* generateCssVars(options, ctx);
yield* endScope();
return ctx;
}

function* generateCssVars(
options: StyleCodegenOptions,
ctx: TemplateCodegenContext,
): Generator<Code> {
for (const style of options.styles) {
for (const binding of style.bindings) {
yield* generateInterpolation(
options,
ctx,
style,
codeFeatures.all,
binding.text,
binding.offset,
`(`,
`)`,
);
yield endOfLine;
}
}
}
13 changes: 9 additions & 4 deletions packages/language-core/lib/codegen/style/modules.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import type { Code } from '../../types';
import { codeFeatures } from '../codeFeatures';
import type { ScriptCodegenOptions } from '../script';
import * as names from '../names';
import type { TemplateCodegenContext } from '../template/context';
import { endOfLine, newLine } from '../utils';
import type { StyleCodegenOptions } from '.';
import { generateClassProperty, generateStyleImports } from './common';

export function* generateStyleModules(
{ styles, scriptSetupRanges, vueCompilerOptions }: ScriptCodegenOptions,
{ styles, vueCompilerOptions }: StyleCodegenOptions,
ctx: TemplateCodegenContext,
): Generator<Code> {
const styleModules = styles.filter(style => style.module);
if (!styleModules.length && !scriptSetupRanges?.useCssModule.length) {
if (!styleModules.length) {
return;
}
yield `type __VLS_StyleModules = {${newLine}`;
ctx.generatedTypes.add(names.StyleModules);

yield `type ${names.StyleModules} = {${newLine}`;
for (const style of styleModules) {
if (style.module === true) {
yield `$style`;
Expand Down
4 changes: 2 additions & 2 deletions packages/language-core/lib/codegen/style/scopedClasses.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { Code } from '../../types';
import type { ScriptCodegenOptions } from '../script';
import { generateStyleScopedClassReference } from '../template/styleScopedClasses';
import { endOfLine } from '../utils';
import type { StyleCodegenOptions } from '.';
import { generateClassProperty, generateStyleImports } from './common';

export function* generateStyleScopedClasses(
{ vueCompilerOptions, styles }: ScriptCodegenOptions,
{ vueCompilerOptions, styles }: StyleCodegenOptions,
): Generator<Code> {
const { resolveStyleClassNames, resolveStyleImports } = vueCompilerOptions;
if (!resolveStyleClassNames) {
Expand Down
Loading