Skip to content

Commit

Permalink
fix(component-parser): function declarations should be typed as acces…
Browse files Browse the repository at this point in the history
…sors, not props (#34)

* fix(component-parser): function declarations should be typed as accessors, not props

* test(writer): update writer-ts-definitions unit test
  • Loading branch information
metonym authored Jul 10, 2021
1 parent 9a84259 commit c9af2fd
Show file tree
Hide file tree
Showing 23 changed files with 975 additions and 13 deletions.
799 changes: 799 additions & 0 deletions integration/carbon/COMPONENT_API.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions integration/glob/COMPONENT_API.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"type": "string",
"value": "\"button2\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -20,6 +21,7 @@
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand Down
5 changes: 5 additions & 0 deletions integration/multi-export-typed/COMPONENT_API.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"type": "\"button\" | \"submit\" | \"reset\"",
"value": "\"button\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -21,6 +22,7 @@
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand Down Expand Up @@ -63,6 +65,7 @@
"type": "string",
"value": "\"\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -72,6 +75,7 @@
"type": "string",
"value": "\"\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand All @@ -98,6 +102,7 @@
"type": "boolean",
"value": "true",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": true,
"reactive": false
}
Expand Down
4 changes: 4 additions & 0 deletions integration/multi-export/COMPONENT_API.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"type": "string",
"value": "\"button\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -20,6 +21,7 @@
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand Down Expand Up @@ -70,6 +72,7 @@
"type": "any",
"value": "\"\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -79,6 +82,7 @@
"type": "Author",
"value": "\"\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand Down
2 changes: 2 additions & 0 deletions integration/single-export/COMPONENT_API.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"type": "string",
"value": "\"button\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -20,6 +21,7 @@
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand Down
6 changes: 5 additions & 1 deletion src/ComponentParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface ComponentProp {
value?: any;
description?: string;
isFunction: boolean;
isFunctionDeclaration: boolean;
reactive: boolean;
}

Expand Down Expand Up @@ -311,6 +312,7 @@ export default class ComponentParser {
let kind = node.declaration.kind;
let description = undefined;
let isFunction = false;
let isFunctionDeclaration = false;

if (init != null) {
if (
Expand Down Expand Up @@ -342,8 +344,9 @@ export default class ComponentParser {
if (declaration_type === "FunctionDeclaration") {
value = "() => " + this.sourceAtPos(body.start, body.end)?.replace(/\n/g, " ");
type = "() => any";
isFunction = true;
kind = "function";
isFunction = true;
isFunctionDeclaration = true;
}

if (node.leadingComments) {
Expand All @@ -365,6 +368,7 @@ export default class ComponentParser {
type,
value,
isFunction,
isFunctionDeclaration,
constant: kind === "const",
reactive: this.reactive_vars.has(prop_name),
});
Expand Down
28 changes: 27 additions & 1 deletion src/writer/writer-ts-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function addCommentLine(value: any, returnValue?: any) {

function genPropDef(def: Pick<ComponentDocApi, "props" | "rest_props" | "moduleName" | "extends">) {
const props = def.props
.filter((prop) => !prop.isFunctionDeclaration)
.map((prop) => {
const prop_comments = [
addCommentLine(prop.description?.replace(/\n/g, "\n* ")),
Expand Down Expand Up @@ -102,6 +103,29 @@ function genEventDef(def: Pick<ComponentDocApi, "events">) {
.join("\n");
}

function genAccessors(def: Pick<ComponentDocApi, "props">) {
return def.props
.filter((prop) => prop.isFunctionDeclaration)
.map((prop) => {
const prop_comments = [
addCommentLine(prop.description?.replace(/\n/g, "\n* ")),
/* addCommentLine(
prop.value,
`@default ${typeof prop.value === "string" ? prop.value.replace(/\s+/g, " ") : prop.value}`
), */
]
.filter(Boolean)
.join("");

let prop_value = /* prop.constant && !prop.isFunction ? prop.value : */ prop.type;

return `
${prop_comments.length > 0 ? `/**\n${prop_comments}*/` : EMPTY_STR}
${prop.name}?: ${prop_value};`;
})
.join("\n");
}

function genImports(def: Pick<ComponentDocApi, "extends">) {
if (def.extends === undefined) return "";
return `import { ${def.extends.interface} } from ${def.extends.import};`;
Expand All @@ -127,7 +151,9 @@ export function writeTsDefinition(component: ComponentDocApi) {
${props_name},
{${genEventDef({ events })}},
{${genSlotDef({ slots })}}
> {}`;
> {
${genAccessors({ props })}
}`;
}

export interface WriteTsDefinitionsOptions {
Expand Down
3 changes: 3 additions & 0 deletions tests/snapshots/bind-this-multiple/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"kind": "let",
"type": "null | HTMLButtonElement | HTMLHeadingElement",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": true
},
Expand All @@ -13,6 +14,7 @@
"kind": "let",
"type": "null | HTMLDivElement",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": true
},
Expand All @@ -22,6 +24,7 @@
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
}
Expand Down
1 change: 1 addition & 0 deletions tests/snapshots/bind-this/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"kind": "let",
"type": "null | HTMLButtonElement",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": true
}
Expand Down
19 changes: 19 additions & 0 deletions tests/snapshots/function-declaration/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script>
export let fnA = () => {};
export const fnB = () => {};
export function add(a, b) {
return a + b;
}
/**
* Multiplies two numbers
* @type {(a: number, b: number) => number}
*/
export function multiply(a, b) {
return a * b;
}
</script>

<h1 on:click={fnA}>Heading</h1>
24 changes: 24 additions & 0 deletions tests/snapshots/function-declaration/output.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// <reference types="svelte" />
import { SvelteComponentTyped } from "svelte";

export interface InputProps {
/**
* @default () => {}
*/
fnA?: () => {};

/**
* @constant
* @default () => {}
*/
fnB?: () => {};
}

export default class Input extends SvelteComponentTyped<InputProps, {}, {}> {
add?: () => any;

/**
* Multiplies two numbers
*/
multiply?: (a: number, b: number) => number;
}
48 changes: 48 additions & 0 deletions tests/snapshots/function-declaration/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"props": [
{
"name": "fnA",
"kind": "let",
"type": "() => {}",
"value": "() => {}",
"isFunction": true,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
{
"name": "fnB",
"kind": "const",
"type": "() => {}",
"value": "() => {}",
"isFunction": true,
"isFunctionDeclaration": false,
"constant": true,
"reactive": false
},
{
"name": "add",
"kind": "function",
"type": "() => any",
"value": "() => { return a + b; }",
"isFunction": true,
"isFunctionDeclaration": true,
"constant": false,
"reactive": false
},
{
"name": "multiply",
"kind": "function",
"description": "Multiplies two numbers",
"type": "(a: number, b: number) => number",
"value": "() => { return a * b; }",
"isFunction": true,
"isFunctionDeclaration": true,
"constant": false,
"reactive": false
}
],
"slots": [],
"events": [],
"typedefs": []
}
7 changes: 2 additions & 5 deletions tests/snapshots/infer-basic/output.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@ export interface InputProps {
* @default { ["1"]: true }
*/
propConst?: { ["1"]: true };
}

/**
* @default () => { localBool = !localBool; }
*/
export default class Input extends SvelteComponentTyped<InputProps, {}, { default: {} }> {
fn?: () => any;
}

export default class Input extends SvelteComponentTyped<InputProps, {}, { default: {} }> {}
7 changes: 7 additions & 0 deletions tests/snapshots/infer-basic/output.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"kind": "let",
"value": "null",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -14,6 +15,7 @@
"type": "boolean",
"value": "true",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": true
},
Expand All @@ -23,13 +25,15 @@
"type": "string",
"value": "\"\"",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
{
"name": "name",
"kind": "let",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -39,6 +43,7 @@
"type": "string",
"value": "\"\" + Math.random().toString(36)",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": false,
"reactive": false
},
Expand All @@ -48,6 +53,7 @@
"type": "{ [\"1\"]: true }",
"value": "{ [\"1\"]: true }",
"isFunction": false,
"isFunctionDeclaration": false,
"constant": true,
"reactive": false
},
Expand All @@ -57,6 +63,7 @@
"type": "() => any",
"value": "() => { localBool = !localBool; }",
"isFunction": true,
"isFunctionDeclaration": true,
"constant": false,
"reactive": false
}
Expand Down
7 changes: 2 additions & 5 deletions tests/snapshots/infer-with-types/output.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@ export interface InputProps {
* @default { ["1"]: true }
*/
propConst?: { ["1"]: true };
}

/**
* @default () => { localBool = !localBool; }
*/
export default class Input extends SvelteComponentTyped<InputProps, {}, { default: {} }> {
fn?: () => any;
}

export default class Input extends SvelteComponentTyped<InputProps, {}, { default: {} }> {}
Loading

0 comments on commit c9af2fd

Please sign in to comment.