Skip to content

Commit

Permalink
feat(component-meta): collect destructured props defaults (#5101)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akryum authored Jan 22, 2025
1 parent 8dfbbc0 commit b41801b
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 14 deletions.
8 changes: 8 additions & 0 deletions packages/component-meta/lib/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,14 @@ function readVueComponentDefaultProps(
...resolvePropsOption(ast, obj, printer, ts),
};
}
} else if (descriptor.scriptSetup && scriptSetupRanges?.defineProps?.destructured) {
const ast = descriptor.scriptSetup.ast;
for (const [prop, initializer] of scriptSetupRanges.defineProps.destructured) {
if (initializer) {
const expText = printer?.printNode(ts.EmitHint.Expression, initializer, ast) ?? initializer.getText(ast);
result[prop] = { default: expText };
}
}
}

function findObjectLiteralExpression(node: ts.Node) {
Expand Down
11 changes: 11 additions & 0 deletions packages/component-meta/tests/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,17 @@ const worker = (checker: ComponentMetaChecker, withTsconfig: boolean) => describ
});
});

test('reference-type-props-destructured', () => {
const componentPath = path.resolve(__dirname, '../../../test-workspace/component-meta/reference-type-props/component-destructure.vue');
const meta = checker.getComponentMeta(componentPath);

expect(meta.type).toEqual(TypeMeta.Class);

const text = meta.props.find(prop => prop.name === 'text');

expect(text?.default).toEqual('"foobar"');
})

test('reference-type-props-js', () => {
const componentPath = path.resolve(__dirname, '../../../test-workspace/component-meta/reference-type-props/component-js.vue');
const meta = checker.getComponentMeta(componentPath);
Expand Down
11 changes: 6 additions & 5 deletions packages/language-core/lib/codegen/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function collectVars(
results: string[] = []
) {
const identifiers = collectIdentifiers(ts, node, []);
for (const [id] of identifiers) {
for (const { id } of identifiers) {
results.push(getNodeText(ts, id, ast));
}
return results;
Expand All @@ -41,15 +41,16 @@ export function collectVars(
export function collectIdentifiers(
ts: typeof import('typescript'),
node: ts.Node,
results: [id: ts.Identifier, isRest: boolean][] = [],
isRest = false
results: Array<{ id: ts.Identifier, isRest: boolean, initializer: ts.Expression | undefined }> = [],
isRest = false,
initializer: ts.Expression | undefined = undefined
) {
if (ts.isIdentifier(node)) {
results.push([node, isRest]);
results.push({ id: node, isRest, initializer });
}
else if (ts.isObjectBindingPattern(node)) {
for (const el of node.elements) {
collectIdentifiers(ts, el.name, results, !!el.dotDotDotToken);
collectIdentifiers(ts, el.name, results, !!el.dotDotDotToken, el.initializer);
}
}
else if (ts.isArrayBindingPattern(node)) {
Expand Down
8 changes: 4 additions & 4 deletions packages/language-core/lib/parsers/scriptSetupRanges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type DefineProp = {

type DefineProps = CallExpressionRange & {
name?: string;
destructured?: Set<string>;
destructured?: Map<string, ts.Expression | undefined>;
destructuredRest?: string;
statement: TextRange;
};
Expand Down Expand Up @@ -285,15 +285,15 @@ export function parseScriptSetupRanges(
};
if (ts.isVariableDeclaration(parent)) {
if (ts.isObjectBindingPattern(parent.name)) {
defineProps.destructured = new Set();
defineProps.destructured = new Map();
const identifiers = collectIdentifiers(ts, parent.name, []);
for (const [id, isRest] of identifiers) {
for (const { id, isRest, initializer } of identifiers) {
const name = _getNodeText(id);
if (isRest) {
defineProps.destructuredRest = name;
}
else {
defineProps.destructured.add(name);
defineProps.destructured.set(name, initializer);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/language-core/lib/plugins/vue-tsx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function createTsx(
);
const destructuredPropNames = unstable.computedSet(
computed(() => {
const newNames = new Set(scriptSetupRanges.get()?.defineProps?.destructured);
const newNames = new Set(scriptSetupRanges.get()?.defineProps?.destructured?.keys());
const rest = scriptSetupRanges.get()?.defineProps?.destructuredRest;
if (rest) {
newNames.add(rest);
Expand Down
8 changes: 4 additions & 4 deletions packages/language-service/lib/plugins/vue-inlayhints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function create(ts: typeof import('typescript')): LanguageServicePlugin {
for (const [prop, isShorthand] of findDestructuredProps(
ts,
virtualCode._sfc.scriptSetup.ast,
scriptSetupRanges.defineProps.destructured
scriptSetupRanges.defineProps.destructured.keys()
)) {
const name = prop.text;
const end = prop.getEnd();
Expand Down Expand Up @@ -117,7 +117,7 @@ type Scope = Record<string, boolean>;
export function findDestructuredProps(
ts: typeof import('typescript'),
ast: ts.SourceFile,
props: Set<string>
props: MapIterator<string>
) {
const rootScope: Scope = Object.create(null);
const scopeStack: Scope[] = [rootScope];
Expand Down Expand Up @@ -192,7 +192,7 @@ export function findDestructuredProps(
&& ts.isCallExpression(initializer)
&& initializer.expression.getText(ast) === 'defineProps';

for (const [id] of collectIdentifiers(ts, name)) {
for (const { id } of collectIdentifiers(ts, name)) {
if (isDefineProps) {
excludedIds.add(id);
} else {
Expand All @@ -208,7 +208,7 @@ export function findDestructuredProps(
}

for (const p of parameters) {
for (const [id] of collectIdentifiers(ts, p)) {
for (const { id } of collectIdentifiers(ts, p)) {
registerLocalBinding(id);
}
}
Expand Down
9 changes: 9 additions & 0 deletions packages/tsc/tests/__snapshots__/dts.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,15 @@ export default _default;
"
`;
exports[`vue-tsc-dts > Input: reference-type-props/component-destructure.vue, Output: reference-type-props/component-destructure.vue.d.ts 1`] = `
"type __VLS_Props = {
text: string;
};
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, HTMLDivElement>;
export default _default;
"
`;
exports[`vue-tsc-dts > Input: reference-type-props/component-js.vue, Output: reference-type-props/component-js.vue.d.ts 1`] = `
"declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
foo: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script lang="ts" setup>
const {
text = 'foobar'
} = defineProps<{
text: string;
}>();
</script>

<template>
<div>{{ text }}</div>
</template>

0 comments on commit b41801b

Please sign in to comment.