diff --git a/CHANGELOG.md b/CHANGELOG.md index 51681a2..956f35c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.0.1 + +- FIX: Fixes [#8](https://github.com/asbjornh/view-models/issues/8) - `typescriptReact` parser crashing when parsing components with no arguments. + ## 2.0.0 - BREAKING: Changes the default file extension for generated TypeScript files from `.ts` to `.d.ts` diff --git a/package.json b/package.json index 3037c9a..ebe8955 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "view-models", - "version": "2.0.0", + "version": "2.0.1", "description": "Generate viewmodels from react components", "main": "lib/index.js", "bin": { diff --git a/source/parsers/prop-types/resolve-references.ts b/source/parsers/prop-types/resolve-references.ts index 6072e35..d21dfdd 100644 --- a/source/parsers/prop-types/resolve-references.ts +++ b/source/parsers/prop-types/resolve-references.ts @@ -3,6 +3,7 @@ import * as t from "@babel/types"; import { MetaTypeTree } from "../../node-types"; +import first from "../../utils/first"; import isObjectMethod from "../utils/is-object-method"; import isMemberExpression from "../utils/is-member-expression"; @@ -29,7 +30,7 @@ export default function resolveReferences( >; const propName: string = propPath.node.key.name; const metaType = meta[propName] ? meta[propName].type : ""; - const argument = path.node.arguments[0]; + const argument = first(path.node.arguments); if (!argument) { throw new Error( @@ -71,7 +72,7 @@ export default function resolveReferences( // Object.keys, Object.values else if (t.isCallExpression(argument) && isObjectMethod(argument)) { const objectMethod = argument; - const methodArg = objectMethod.arguments[0]; + const methodArg = first(objectMethod.arguments); if (!methodArg) { throw new Error( diff --git a/source/parsers/typescript-react/get-prop-types.ts b/source/parsers/typescript-react/get-prop-types.ts index 7f0a469..012ff60 100644 --- a/source/parsers/typescript-react/get-prop-types.ts +++ b/source/parsers/typescript-react/get-prop-types.ts @@ -3,6 +3,7 @@ import * as t from "@babel/types"; import getDefinitionName from "./get-definition-name"; import filter from "../../utils/filter"; +import first from "../../utils/first"; export default function getPropTypes(ast: t.File, componentName: string) { let typeName: string | undefined; @@ -46,16 +47,16 @@ export default function getPropTypes(ast: t.File, componentName: string) { if (!t.isIdentifier(path.parent.id)) return; if (path.parent.id.name !== componentName) return; - const arg = path.node.params[0]; + const firstArg = first(path.node.params); - if (t.isTSParameterProperty(arg)) + if (t.isTSParameterProperty(firstArg)) throw new Error(`Unexpected parameter property`); - if (t.isNoop(arg.typeAnnotation)) + if (t.isNoop(firstArg?.typeAnnotation)) throw new Error(`Unexpected noop in type annotation`); - if (arg.typeAnnotation) { - const argType = arg.typeAnnotation.typeAnnotation; + if (firstArg?.typeAnnotation) { + const argType = firstArg.typeAnnotation.typeAnnotation; if (t.isTSTypeReference(argType)) { const name = getDefinitionName(argType.typeName); types = typeDeclarations[name]; @@ -76,7 +77,7 @@ export default function getPropTypes(ast: t.File, componentName: string) { if (!t.isTSTypeReference(funcType)) return; if (funcType.typeParameters !== null) { - const type = funcType.typeParameters.params[0]; + const type = first(funcType.typeParameters.params); if (t.isTSTypeReference(type)) { const name = getDefinitionName(type.typeName); types = typeDeclarations[name]; diff --git a/source/parsers/typescript-react/typescript-react.test.js b/source/parsers/typescript-react/typescript-react.test.js index 5809a89..f2e15db 100644 --- a/source/parsers/typescript-react/typescript-react.test.js +++ b/source/parsers/typescript-react/typescript-react.test.js @@ -33,6 +33,17 @@ test( classes.funcComponent ); +test( + "Component without props argument", + template, + `const Component: React.FunctionComponent<{}> = () => null; + export default Component;`, + `${csharpImports} + public class Component + { + }` +); + test( "Empty component", template, diff --git a/source/utils/first.ts b/source/utils/first.ts new file mode 100644 index 0000000..90e54a7 --- /dev/null +++ b/source/utils/first.ts @@ -0,0 +1,4 @@ +/* Utility function for safely getting the first element of an array */ +export default function first(arr: T[]): T | undefined { + return arr[0]; +}