Skip to content

Commit

Permalink
fix: import macros on-demand
Browse files Browse the repository at this point in the history
  • Loading branch information
so1ve committed Sep 9, 2023
1 parent 97d60fa commit 3063f80
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 10 deletions.
11 changes: 10 additions & 1 deletion packages/vue-language-core/src/generators/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Sfc } from '../types';
import * as sharedTypes from '../utils/globalTypes';
import { getSlotsPropertyName, hyphenateTag } from '../utils/shared';
import { walkInterpolationFragment } from '../utils/transform';
import { defaultMacros } from '../utils/ts';

export function generate(
ts: typeof import('typescript/lib/tsserverlibrary'),
Expand Down Expand Up @@ -63,6 +64,7 @@ export function generate(
slotsTypeArg: undefined,
withDefaultsArg: undefined,
defineProp: [],
macrosToBeImported: defaultMacros,
};
}
//#endregion
Expand Down Expand Up @@ -464,7 +466,14 @@ export function generate(
const definePropProposalB = sfc.scriptSetup.content.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition') || vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';

if (vueCompilerOptions.target >= 3.3) {
codes.push(`const { defineProps, defineEmits, defineExpose, defineOptions, defineSlots, defineModel, withDefaults } = await import('${vueCompilerOptions.lib}');\n`);
codes.push('const { ');
for (const [macro, aliases] of Object.entries(scriptSetupRanges.macrosToBeImported)) {
if (!aliases.length) continue;
for (const alias of aliases) {
codes.push(`${macro}: ${alias}, `);
}
}
codes.push(` } = await import('${vueCompilerOptions.lib}');\n`);
}
if (definePropProposalA) {
codes.push(`
Expand Down
30 changes: 28 additions & 2 deletions packages/vue-language-core/src/parsers/scriptSetupRanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ export function parseScriptSetupRanges(
const bindings = parseBindingRanges(ts, ast, false);
const text = ast.getFullText();
const leadingCommentEndOffset = ts.getLeadingCommentRanges(text, 0)?.reverse()[0].end ?? 0;
const macrosToBeImported: VueCompilerOptions['macros'] = {
defineProps: vueCompilerOptions.macros.defineProps,
defineSlots: vueCompilerOptions.macros.defineSlots,
defineEmits: vueCompilerOptions.macros.defineEmits,
defineExpose: vueCompilerOptions.macros.defineExpose,
defineModel: vueCompilerOptions.macros.defineModel,
defineOptions: vueCompilerOptions.macros.defineOptions,
withDefaults: vueCompilerOptions.macros.withDefaults,
};

ast.forEachChild(node => {
const isTypeExport = (ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword);
Expand Down Expand Up @@ -75,18 +84,35 @@ export function parseScriptSetupRanges(
emitsTypeNums,
exposeRuntimeArg,
defineProp,
macrosToBeImported,
};

function _getStartEnd(node: ts.Node) {
return getStartEnd(node, ast);
}
function visitNode(node: ts.Node, parent: ts.Node) {
if (
if (ts.isVariableDeclaration(node) || ts.isFunctionDeclaration(node)) {
const name = node.name?.getText(ast);
if (name && name in macrosToBeImported) {
for (const key in macrosToBeImported) {
macrosToBeImported[key as keyof VueCompilerOptions['macros']] = macrosToBeImported[key as keyof VueCompilerOptions['macros']].filter(macro => macro !== name);
}
}
}
else if (ts.isImportSpecifier(node)) {
const name = node.name.getText(ast);
if (name in macrosToBeImported) {
for (const key in macrosToBeImported) {
macrosToBeImported[key as keyof VueCompilerOptions['macros']] = macrosToBeImported[key as keyof VueCompilerOptions['macros']].filter(macro => macro !== name);
}
}
}
else if (
ts.isCallExpression(node)
&& ts.isIdentifier(node.expression)
) {
const callText = node.expression.getText(ast);
if (callText === 'defineModel') {
if (vueCompilerOptions.macros.defineModel.includes(callText)) {
let name: TextRange | undefined;
let options: ts.Node | undefined;
if (node.arguments.length >= 2) {
Expand Down
2 changes: 2 additions & 0 deletions packages/vue-language-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export interface VueCompilerOptions {
defineSlots: string[];
defineEmits: string[];
defineExpose: string[];
defineModel: string[];
defineOptions: string[];
withDefaults: string[];
};
plugins: VueLanguagePlugin[];
Expand Down
18 changes: 11 additions & 7 deletions packages/vue-language-core/src/utils/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,16 @@ const SVG_TAGS =
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';

export const defaultMacros: VueCompilerOptions['macros'] = {
defineProps: ['defineProps'],
defineSlots: ['defineSlots'],
defineEmits: ['defineEmits'],
defineExpose: ['defineExpose'],
defineModel: ['defineModel'],
defineOptions: ['defineOptions'],
withDefaults: ['withDefaults'],
};

export function resolveVueCompilerOptions(vueOptions: Partial<VueCompilerOptions>): VueCompilerOptions {
const target = vueOptions.target ?? 3.3;
const lib = vueOptions.lib || (target < 2.7 ? '@vue/runtime-dom' : 'vue');
Expand All @@ -257,13 +267,7 @@ export function resolveVueCompilerOptions(vueOptions: Partial<VueCompilerOptions
? [`(await import('${lib}')).defineComponent(`, `)`]
: [`(await import('vue')).default.extend(`, `)`]
),
macros: vueOptions.macros ?? {
defineProps: ['defineProps'],
defineSlots: ['defineSlots'],
defineEmits: ['defineEmits'],
defineExpose: ['defineExpose'],
withDefaults: ['withDefaults'],
},
macros: vueOptions.macros ?? defaultMacros,
plugins: vueOptions.plugins ?? [],
hooks: vueOptions.hooks ?? [],

Expand Down

0 comments on commit 3063f80

Please sign in to comment.