Skip to content

Commit

Permalink
fix: incorrect typedef parsing for interfaces (#24192)
Browse files Browse the repository at this point in the history
* fix: incorrect typedef parsing for interfaces

Wasn't finding typedefs for interfaces with the same name as the typed thing; e.g.

```ts
interface Foo {}
const Foo: Foo
```

Also adds a guard and more helpful error when unavoidable loops occur due to type naming

* test: add tests
  • Loading branch information
jquense committed Jul 3, 2020
1 parent baddf58 commit 1a1177e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 16 deletions.
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`transformer-react-doc-gen: onCreateNode Complex example should handle members should handle type unions 1`] = `
exports[`gatsby-transformer-documentationjs: onCreateNode Complex example should handle members should handle type unions 1`] = `
Object {
"elements": Array [
Object {
Expand All @@ -18,7 +18,7 @@ Object {
}
`;

exports[`transformer-react-doc-gen: onCreateNode Complex example should handle typedefs should handle type applications 1`] = `
exports[`gatsby-transformer-documentationjs: onCreateNode Complex example should handle typedefs should handle type applications 1`] = `
Object {
"children": Array [
"documentationJS documentationJS node_1 path #[{\\"name\\":\\"ObjectType\\",\\"kind\\":\\"typedef\\"}] line 12 path #[{\\"name\\":\\"ObjectType\\",\\"kind\\":\\"typedef\\"},{\\"fieldName\\":\\"properties\\",\\"fieldIndex\\":0}] line 3--DocumentationJSComponentDescription--comment.description",
Expand Down Expand Up @@ -52,12 +52,12 @@ Object {
}
`;

exports[`transformer-react-doc-gen: onCreateNode Simple example should extract out a description, params, and examples: description content 1`] = `
exports[`gatsby-transformer-documentationjs: onCreateNode Simple example should extract out a description, params, and examples: description content 1`] = `
"A pretty cool jsdoc example
"
`;

exports[`transformer-react-doc-gen: onCreateNode Simple example should extract out a description, params, and examples: example 1`] = `
exports[`gatsby-transformer-documentationjs: onCreateNode Simple example should extract out a description, params, and examples: example 1`] = `
Object {
"description": "const apple = require('apple')
apple()",
Expand All @@ -68,9 +68,9 @@ apple()",
}
`;
exports[`transformer-react-doc-gen: onCreateNode Simple example should extract out a description, params, and examples: param description 1`] = `
exports[`gatsby-transformer-documentationjs: onCreateNode Simple example should extract out a description, params, and examples: param description 1`] = `
"A nice crispy apple
"
`;
exports[`transformer-react-doc-gen: onCreateNode Simple example should extract out a description, params, and examples: param name 1`] = `"paramName"`;
exports[`gatsby-transformer-documentationjs: onCreateNode Simple example should extract out a description, params, and examples: param name 1`] = `"paramName"`;
@@ -0,0 +1,14 @@

/**
* The actual type
*/
export declare interface Foo {
(props: any): JSX.Element | null;
}

/**
* The Main Thing here
*/
const Foo: Foo = () => null;


Expand Up @@ -2,7 +2,7 @@ import groupBy from "lodash/groupBy"
import path from "path"
import gatsbyNode from "../gatsby-node"

describe(`transformer-react-doc-gen: onCreateNode`, () => {
describe(`gatsby-transformer-documentationjs: onCreateNode`, () => {
let createdNodes, updatedNodes
const createNodeId = jest.fn(id => id)
const createContentDigest = jest.fn().mockReturnValue(`content-digest`)
Expand Down Expand Up @@ -361,4 +361,8 @@ describe(`transformer-react-doc-gen: onCreateNode`, () => {
expect(createdNodes.length).toBeGreaterThan(0)
})
})

it(`doesn't cause a stack overflow for nodes of the same name`, () => {
expect(run(getFileNode(`same-name.ts`))).resolves.toBeUndefined()
})
})
25 changes: 16 additions & 9 deletions packages/gatsby-transformer-documentationjs/src/gatsby-node.js
Expand Up @@ -218,18 +218,25 @@ exports.onCreateNode = async ({ node, actions, ...helpers }) => {
const handledDocs = new WeakMap()
const typeDefs = new Map()

const getNodeIDForType = typeName => {
const getNodeIDForType = (typeName, parent) => {
if (typeDefs.has(typeName)) {
return typeDefs.get(typeName)
}

const index = documentationJson.findIndex(
docsJson =>
docsJson.name === typeName &&
[`typedef`, `constant`].includes(docsJson.kind)
[`interface`, `typedef`, `constant`].includes(docsJson.kind)
)

if (index !== -1) {
const isCycle = parent === documentationJson[index]
if (isCycle) {
helpers.reporter.warn(
`Unexpected cycle detected creating DocumentationJS nodes for file:\n\n\t${node.absolutePath}\n\nFor type: ${typeName}`
)
}

if (index !== -1 && !isCycle) {
return prepareNodeForDocs(documentationJson[index], {
commentNumber: index,
}).node.id
Expand All @@ -238,21 +245,21 @@ exports.onCreateNode = async ({ node, actions, ...helpers }) => {
return null
}

const tryToAddTypeDef = type => {
const tryToAddTypeDef = (type, parent) => {
if (type.applications) {
type.applications.forEach(tryToAddTypeDef)
type.applications.forEach(t => tryToAddTypeDef(t, parent))
}

if (type.expression) {
tryToAddTypeDef(type.expression)
tryToAddTypeDef(type.expression, parent)
}

if (type.elements) {
type.elements.forEach(tryToAddTypeDef)
type.elements.forEach(t => tryToAddTypeDef(t, parent))
}

if (type.type === `NameExpression` && type.name) {
type.typeDef___NODE = getNodeIDForType(type.name)
type.typeDef___NODE = getNodeIDForType(type.name, parent)
}
}

Expand Down Expand Up @@ -334,7 +341,7 @@ exports.onCreateNode = async ({ node, actions, ...helpers }) => {
picked.type = picked.type.expression
}

tryToAddTypeDef(picked.type)
tryToAddTypeDef(picked.type, docsJson)
}

const mdFields = [`description`, `deprecated`]
Expand Down

0 comments on commit 1a1177e

Please sign in to comment.