From 615007528a9c270e9b403e203f3f564e1c3d8422 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Fri, 29 Dec 2023 13:28:47 -0700 Subject: [PATCH] Detect default values on destructured parameters Resolves #2430 --- CHANGELOG.md | 1 + src/lib/converter/factories/signature.ts | 22 +++++++++++++++++++ src/test/converter/variables/specs.json | 9 +++++--- src/test/converter/variables/specs.nodoc.json | 9 +++++--- src/test/converter2/issues/gh2430.js | 11 ++++++++++ src/test/issues.c2.test.ts | 19 ++++++++++++++++ 6 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 src/test/converter2/issues/gh2430.js diff --git a/CHANGELOG.md b/CHANGELOG.md index ca7590bab..e49d2cd92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - TypeDoc now inherits `typedocOptions` fields from extended tsconfig files, #2334. - Methods which return function types no longer have duplicated comments, #2336. - Comments on function-like type aliases will now show up under the type alias, rather than nested within the type declaration, #2372. +- Improved detection of default values for parameters with destructured values, #2430. - Fix crash when converting some complicated union/intersection types, #2451. - Navigation triangle markers should no longer display on a separate line with some font settings, #2457. - `@group` and `@category` organization is now applied later to allow inherited comments to create groups/categories, #2459. diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index 673094cfe..ab1578d24 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -214,6 +214,7 @@ function convertParameters( } paramRefl.setFlag(ReflectionFlag.Rest, isRest); + checkForDestructuredParameterDefaults(paramRefl, parameterNodes?.[i]); return paramRefl; }); } @@ -261,10 +262,31 @@ export function convertParameterNodes( : !!param.typeExpression && ts.isJSDocVariadicType(param.typeExpression.type), ); + checkForDestructuredParameterDefaults(paramRefl, param); return paramRefl; }); } +function checkForDestructuredParameterDefaults( + param: ParameterReflection, + decl: ts.ParameterDeclaration | ts.JSDocParameterTag | undefined, +) { + if (!decl || !ts.isParameter(decl)) return; + if (param.name !== "__namedParameters") return; + if (!ts.isObjectBindingPattern(decl.name)) return; + if (param.type?.type !== "reflection") return; + + for (const child of param.type.declaration.children || []) { + const tsChild = decl.name.elements.find( + (el) => (el.propertyName || el.name).getText() === child.name, + ); + + if (tsChild) { + child.defaultValue = convertDefaultValue(tsChild); + } + } +} + function convertTypeParameters( context: Context, parent: Reflection, diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 80b64cc9c..6eb4cefe7 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -687,7 +687,8 @@ "name": "boolean" } ] - } + }, + "defaultValue": "false" }, { "id": 21, @@ -716,7 +717,8 @@ ] } ] - } + }, + "defaultValue": "..." }, { "id": 20, @@ -736,7 +738,8 @@ "name": "string" } ] - } + }, + "defaultValue": "\"\"" } ], "groups": [ diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index da68bef17..83567507f 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -327,7 +327,8 @@ "name": "boolean" } ] - } + }, + "defaultValue": "false" }, { "id": 21, @@ -356,7 +357,8 @@ ] } ] - } + }, + "defaultValue": "..." }, { "id": 20, @@ -376,7 +378,8 @@ "name": "string" } ] - } + }, + "defaultValue": "\"\"" } ], "groups": [ diff --git a/src/test/converter2/issues/gh2430.js b/src/test/converter2/issues/gh2430.js new file mode 100644 index 000000000..fff19d4c6 --- /dev/null +++ b/src/test/converter2/issues/gh2430.js @@ -0,0 +1,11 @@ +/** + * @param {object} props + * @param {any} props.value Value + * @param {any} props.trueValue True default + * @param {any} props.falseValue False default + */ +export const Checkbox = ({ + value, + trueValue = true, + falseValue: renamed = false, +}) => {}; diff --git a/src/test/issues.c2.test.ts b/src/test/issues.c2.test.ts index f6d5d2c46..ef7ceac9d 100644 --- a/src/test/issues.c2.test.ts +++ b/src/test/issues.c2.test.ts @@ -1276,6 +1276,25 @@ describe("Issue Tests", () => { ); }); + it("Handles destructured object parameter defaults, #2430", () => { + const project = convert(); + const Checkbox = querySig(project, "Checkbox"); + equal(Checkbox.parameters?.length, 1); + equal(Checkbox.parameters[0].name, "props"); + const type = Checkbox.parameters[0].type; + equal(type?.type, "reflection"); + equal(type.declaration.children?.map((c) => c.name), [ + "falseValue", + "trueValue", + "value", + ]); + equal(type.declaration.children?.map((c) => c.defaultValue), [ + "false", + "true", + undefined, + ]); + }); + it("Handles function-namespaces created with Object.assign #2436", () => { const project = convert(); equal(query(project, "bug").kind, ReflectionKind.Function);