Skip to content

Commit

Permalink
Better support for typedef @Property (#135)
Browse files Browse the repository at this point in the history
* Better support for typedef @Property

Given the following JSDoc

```js
/**
 * @typedef {Object} BillboardGraphics.ConstructorOptions
 *
 * Initialization options for the BillboardGraphics constructor
 *
 * @Property {Property | boolean} [show=true] A boolean Property specifying the visibility of the billboard.
 */
```

tsd-jsdoc was producing the following TS code

```ts
/**
 * Initialization options for the BillboardGraphics constructor
 * @Property [show = true] - A boolean Property specifying the visibility of the billboard.
 */
type ConstructorOptions = {
    show?: Property | boolean;
};
```

`@property` is not valid TS markup and the actual property, show, does
not include it's description or default value.

After this change the same JSDoc markup produces much nicer code that
handles both of these:

```ts
/**
 * Initialization options for the BillboardGraphics constructor
 */
type ConstructorOptions = {
    /**
     * A boolean property specifying the visibility of the billboard.
     * @DefaultValue true
     */
    show?: Property | boolean;
};
```

I updated the tests, to match the new output and manually verified its
what I would expect.

* Update src/type_resolve_helpers.ts

Co-authored-by: Chad Engler <[email protected]>

* Update src/type_resolve_helpers.ts

Co-authored-by: Chad Engler <[email protected]>

* Style fixes

Co-authored-by: Chad Engler <[email protected]>
  • Loading branch information
mramato and englercj authored Jun 3, 2020
1 parent 315b7fa commit 3c6e2db
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 51 deletions.
7 changes: 6 additions & 1 deletion src/create_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,14 @@ function handleComment<T extends ts.Node>(doclet: TDoclet, node: T): T
{
let comment = `*${description}${examples}${properties}${params}${returns}
`;
if (doclet.kind === 'typedef')
{
// typedef properties are written out at the member.
comment = `*${description}${examples}${params}${returns}
`;
}

const kind = ts.SyntaxKind.MultiLineCommentTrivia;

ts.addSyntheticLeadingComment(node, kind, comment, true);
}
}
Expand Down
20 changes: 18 additions & 2 deletions src/type_resolve_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -740,13 +740,29 @@ export function createTypeLiteral(children: IPropDesc[], parent?: IPropDesc): ts
const opt = node.prop.optional ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined;
const t = node.children.length ? createTypeLiteral(node.children, node) : resolveType(node.prop.type);

members.push(ts.createPropertySignature(
const property = ts.createPropertySignature(
undefined, // modifiers
node.name, // name
opt, // questionToken
t, // type
undefined // initializer
));
);

// !parent ensures we are dealing with a top-level typedef.
// So that the tsd-doc is added at the property level.
if (!parent && (node.prop.description || node.prop.defaultvalue))
{
let comment = `*\n `;
if (node.prop.description)
comment += `* ${node.prop.description.split(/\r\s*/).join("\n * ")}\n `;

if (node.prop.defaultvalue)
comment += `* @defaultValue ${node.prop.defaultvalue}\n `;

ts.addSyntheticLeadingComment(property, ts.SyntaxKind.MultiLineCommentTrivia, comment, true);
}

members.push(property);
}

let node: ts.TypeNode = ts.createTypeLiteralNode(members);
Expand Down
119 changes: 71 additions & 48 deletions test/expected/typedef_all.d.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
declare module "typedefs" {
/**
* The complete Triforce, or one or more components of the Triforce.
* @property hasCourage - Indicates whether the Courage component is present.
* @property hasPower - Indicates whether the Power component is present.
* @property hasWisdom - Indicates whether the Wisdom component is present.
*/
type Triforce = {
/**
* Indicates whether the Courage component is present.
*/
hasCourage: boolean;
/**
* Indicates whether the Power component is present.
*/
hasPower: boolean;
/**
* Indicates whether the Wisdom component is present.
*/
hasWisdom: boolean;
};
/**
* The complete Triforce, or one or more components of the Triforce.
* @property hasCourage - Indicates whether the Courage component is present.
* @property hasPower - Indicates whether the Power component is present.
* @property hasWisdom - Indicates whether the Wisdom component is present.
*/
type Anon = {
/**
* Indicates whether the Courage component is present.
*/
hasCourage: boolean;
/**
* Indicates whether the Power component is present.
*/
hasPower: boolean;
/**
* Indicates whether the Wisdom component is present.
*/
hasWisdom: boolean;
thing: {
a: {
Expand All @@ -30,68 +42,64 @@ declare module "typedefs" {
};
};
/**
* @property [elementId = "gitGraph"] - Id of the canvas container
* @property [template] - Template of the graph
* @property [author = "Sergio Flores <[email protected]>"] - Default author for commits
* @property [mode = (null|"compact")] - Display mode
* @property [canvas] - DOM canvas (ex: document.getElementById("id"))
* @property [orientation = ("vertical-reverse"|"horizontal"|"horizontal-reverse")] - Graph orientation
* @property [reverseArrow = false] - Make arrows point to ancestors if true
* @property [initCommitOffsetX = 0] - Add custom offsetX to initial commit.
* @property [initCommitOffsetY = 0] - Add custom offsetY to initial commit.
* @property [tooltipContainer = document.body] - HTML Element containing tooltips in compact mode.
*/
type GitGraphOptions = {
/**
* Id of the canvas container
* @defaultValue "gitGraph"
*/
elementId?: string;
/**
* Template of the graph
*/
template?: Template | string | any;
/**
* Default author for commits
* @defaultValue "Sergio Flores <[email protected]>"
*/
author?: string;
/**
* Display mode
* @defaultValue (null|"compact")
*/
mode?: string;
/**
* DOM canvas (ex: document.getElementById("id"))
*/
canvas?: HTMLElement;
/**
* Graph orientation
* @defaultValue ("vertical-reverse"|"horizontal"|"horizontal-reverse")
*/
orientation?: string;
/**
* Make arrows point to ancestors if true
*/
reverseArrow?: boolean;
/**
* Add custom offsetX to initial commit.
*/
initCommitOffsetX?: number;
/**
* Add custom offsetY to initial commit.
*/
initCommitOffsetY?: number;
/**
* HTML Element containing tooltips in compact mode.
* @defaultValue document.body
*/
tooltipContainer?: HTMLElement;
};
/**
* A number, or a string containing a number.
*/
type NumberLike = number | string;
/**
* @property pattern - Holds a pattern definition.
* @property pattern.image - URL to an image to use as the pattern.
* @property pattern.width - Width of the pattern. For images this is
* automatically set to the width of the element bounding box if not supplied.
* For non-image patterns the default is 32px. Note that automatic resizing of
* image patterns to fill a bounding box dynamically is only supported for
* patterns with an automatically calculated ID.
* @property pattern.height - Analogous to pattern.width.
* @property pattern.aspectRatio - For automatically calculated width and
* height on images, it is possible to set an aspect ratio. The image will be
* zoomed to fill the bounding box, maintaining the aspect ratio defined.
* @property pattern.x - Horizontal offset of the pattern. Defaults to 0.
* @property pattern.y - Vertical offset of the pattern. Defaults to 0.
* @property pattern.path - Either an SVG path as string, or an
* object. As an object, supply the path string in the `path.d` property. Other
* supported properties are standard SVG attributes like `path.stroke` and
* `path.fill`. If a path is supplied for the pattern, the `image` property is
* ignored.
* @property pattern.color - Pattern color, used as default path stroke.
* @property pattern.opacity - Opacity of the pattern as a float value
* from 0 to 1.
* @property pattern.id - ID to assign to the pattern. This is
* automatically computed if not added, and identical patterns are reused. To
* refer to an existing pattern for a Highcharts color, use
* `color: "url(#pattern-id)"`.
* @property animation - Animation options for the image pattern
* loading.
* Note: doesn't matter what I put, a @property only gets "FUNCTION" from jsdoc
* @property rotate - Rotates the pattern by degrees
* @property wiggle - Wiggles the pattern (default function)
* @property wobble - Wobbles the pattern
* (complex function)
*/
type PatternOptions = {
/**
* Holds a pattern definition.
*/
pattern: {
image: string;
width: number;
Expand All @@ -104,9 +112,24 @@ declare module "typedefs" {
opacity: number;
id: string;
};
/**
* Animation options for the image pattern
loading.
Note: doesn't matter what I put, a @property only gets "FUNCTION" from jsdoc
*/
animation: any | boolean;
/**
* Rotates the pattern by degrees
*/
rotate: (...params: any[]) => any;
/**
* Wiggles the pattern (default function)
*/
wiggle: (...params: any[]) => any;
/**
* Wobbles the pattern
(complex function)
*/
wobble: (...params: any[]) => any;
};
}

0 comments on commit 3c6e2db

Please sign in to comment.