Skip to content

Commit

Permalink
Merge pull request #12 from pvasek/fix/HOC_not_working_for_external_f…
Browse files Browse the repository at this point in the history
…unctions

HOC not working for external functions
  • Loading branch information
pvasek authored May 4, 2017
2 parents 340df1d + 0aa98f3 commit 2d90d95
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 57 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-docgen-typescript",
"version": "0.0.9",
"version": "0.0.10",
"description": "",
"main": "lib/index.js",
"scripts": {
Expand All @@ -21,7 +21,7 @@
"devDependencies": {
"@types/chai": "^3.4.35",
"@types/mocha": "^2.2.39",
"@types/node": "^7.0.5",
"@types/node": "^7.0.16",
"@types/react": "^15.0.14",
"@types/react-dom": "^0.14.23",
"babel-core": "^6.8.0",
Expand Down
16 changes: 10 additions & 6 deletions src/__tests__/data/ColumnHigherOrderComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import { externalHoc } from "./ColumnHigherOrderComponentHoc";
/**
* Column properties.
*/
Expand Down Expand Up @@ -62,13 +63,16 @@ function hoc<T>(C: T): T {
return ((props) => <div>{C}</div>) as any as T;
}

/** ColumnHighOrderComponent1 specific comment */
export const ColumnHighOrderComponent1 = hoc(Column);
/** ColumnHigherOrderComponent1 specific comment */
export const ColumnHigherOrderComponent1 = hoc(Column);

export const ColumnHighOrderComponent2 = hoc(Column);
export const ColumnHigherOrderComponent2 = hoc(Column);

/** RowHighOrderComponent1 specific comment */
export const RowHighOrderComponent1 = hoc(Row);
/** RowHigherOrderComponent1 specific comment */
export const RowHigherOrderComponent1 = hoc(Row);

export const RowHighOrderComponent2 = hoc(Row);
export const RowHigherOrderComponent2 = hoc(Row);

export const ColumnExternalHigherOrderComponent = externalHoc(Column);
export const RowExternalHigherOrderComponent = externalHoc(Row);

5 changes: 5 additions & 0 deletions src/__tests__/data/ColumnHigherOrderComponentHoc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as React from 'react';

export function externalHoc<T>(C: T): T {
return ((props) => <div>{C}</div>) as any as T;
}
16 changes: 14 additions & 2 deletions src/__tests__/data/transformAST.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { externalHoc } from './transformAST_hoc';

const unexportedVar = 10;
export const exportedVar = 10;

Expand Down Expand Up @@ -51,5 +53,15 @@ export function hoc<T>(component: T): T {
return component;
}

/** exportedHoc comment */
export const exportedHoc = hoc(ExportedClass);
/** exportedHoc1 comment */
export const exportedHoc1 = hoc(ExportedClass);

/** exportedHoc2 comment */
export const exportedHoc2 = hoc(exportedFunction);


/** exportedExternalHoc1 comment */
export const exportedExternalHoc1 = externalHoc(ExportedClass);

/** exportedExternalHoc2 comment */
export const exportedExternalHoc2 = externalHoc(exportedFunction);
3 changes: 3 additions & 0 deletions src/__tests__/data/transformAST_hoc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function externalHoc<T>(component: T): T {
return component;
}
75 changes: 54 additions & 21 deletions src/__tests__/getFileDocumentation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,39 +173,72 @@ describe('getFileDocumentation', () => {
const fileName = path.join(__dirname, '../../src/__tests__/data/ColumnHigherOrderComponent.tsx'); // it's running in ./temp
const result = getFileDocumentation(fileName);
assert.ok(result.components);
assert.equal(4, result.components.length);
assert.equal(6, result.components.length);

const r1 = result.components[0];
assert.equal('ColumnHighOrderComponent1', r1.name);
assert.equal('ColumnHighOrderComponent1 specific comment', r1.comment);
assert.equal('ColumnHigherOrderComponent1', r1.name);
assert.equal('ColumnHigherOrderComponent1 specific comment', r1.comment);
assert.equal('Column', r1.extends);
assert.isNotNull(r1.propInterface);

const i = r1.propInterface;
assert.equal('IColumnProps', i.name);
assert.equal('Column properties.', i.comment);
assert.equal(4, i.members.length);
assert.equal('prop1', i.members[0].name);
assert.equal('prop1 description', i.members[0].comment);
assert.equal(false, i.members[0].isRequired);
const p1 = r1.propInterface;
assert.equal('IColumnProps', p1.name);
assert.equal('Column properties.', p1.comment);
assert.equal(4, p1.members.length);
assert.equal('prop1', p1.members[0].name);
assert.equal('prop1 description', p1.members[0].comment);
assert.equal(false, p1.members[0].isRequired);

assert.equal('prop2', i.members[1].name);
assert.equal('prop2 description', i.members[1].comment);
assert.equal(true, i.members[1].isRequired);
assert.equal('prop2', p1.members[1].name);
assert.equal('prop2 description', p1.members[1].comment);
assert.equal(true, p1.members[1].isRequired);

assert.equal('prop3', i.members[2].name);
assert.equal('prop3 description', i.members[2].comment);
assert.equal(true, i.members[2].isRequired);
assert.equal('prop3', p1.members[2].name);
assert.equal('prop3 description', p1.members[2].comment);
assert.equal(true, p1.members[2].isRequired);

assert.equal('prop4', i.members[3].name);
assert.equal('prop4 description', i.members[3].comment);
assert.equal(true, i.members[3].isRequired);
assert.equal('prop4', p1.members[3].name);
assert.equal('prop4 description', p1.members[3].comment);
assert.equal(true, p1.members[3].isRequired);

const r2 = result.components[1];
assert.equal('ColumnHighOrderComponent2', r2.name);
assert.equal('ColumnHigherOrderComponent2', r2.name);
assert.equal('Form column.', r2.comment);
assert.equal('Column', r2.extends);
assert.isNotNull(r2.propInterface);

const p2 = r2.propInterface;
assert.equal('IColumnProps', p2.name);

const r3 = result.components[2];
assert.equal('ColumnExternalHigherOrderComponent', r3.name);
assert.equal('Form column.', r3.comment);
assert.equal('Column', r3.extends);
assert.isNotNull(r3.propInterface);
const p3 = r3.propInterface;
assert.equal('IColumnProps', p3.name);

const r4 = result.components[3];
assert.equal('RowHigherOrderComponent1', r4.name);
assert.equal('RowHigherOrderComponent1 specific comment', r4.comment);
assert.equal('Row', r4.extends);
assert.isNotNull(r4.propInterface);
const p4 = r4.propInterface;
assert.equal('IRowProps', p4.name);

const r5 = result.components[4];
assert.equal('RowHigherOrderComponent2', r5.name);
assert.equal('Form row.', r5.comment);
assert.equal('Row', r5.extends);
assert.isNotNull(r5.propInterface);
const p5 = r5.propInterface;
assert.equal('IRowProps', p5.name);

const r6 = result.components[5];
assert.equal('RowExternalHigherOrderComponent', r6.name);
assert.equal('Form row.', r6.comment);
assert.equal('Row', r6.extends);
assert.isNotNull(r6.propInterface);
const p6 = r6.propInterface;
assert.equal('IRowProps', p6.name);
});
});
35 changes: 31 additions & 4 deletions src/__tests__/transformAST.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('transformAST', () => {

it('should provide data about variables', () => {
const result = target.variables;
assert.equal(result.length, 5);
assert.equal(result.length, 8);

const r1 = result[0];
assert.equal(r1.name, 'unexportedVar');
Expand Down Expand Up @@ -48,14 +48,41 @@ describe('transformAST', () => {
assert.equal(r4.arrowFunctionType, 'string');
assert.deepEqual(r4.arrowFunctionParams, ['number', 'string']);

// hoc
// hoc class
const r5 = result[4];
assert.equal(r5.name, 'exportedHoc');
assert.equal(r5.name, 'exportedHoc1');
assert.equal(r5.exported, true);
assert.equal(r5.type, 'ExportedClass');
assert.equal(r5.kind, 'callExpression');
assert.equal(r5.comment, 'exportedHoc comment');
assert.equal(r5.comment, 'exportedHoc1 comment');
assert.deepEqual(r5.callExpressionArguments, ['ExportedClass']);

// hoc function
const r6 = result[5];
assert.equal(r6.name, 'exportedHoc2');
assert.equal(r6.exported, true);
assert.equal(r6.type, 'exportedFunction');
assert.equal(r6.kind, 'callExpression');
assert.equal(r6.comment, 'exportedHoc2 comment');
assert.deepEqual(r6.callExpressionArguments, ['exportedFunction']);

// external hoc class
const r7 = result[6];
assert.equal(r7.name, 'exportedExternalHoc1');
assert.equal(r7.exported, true);
assert.equal(r7.type, 'ExportedClass');
assert.equal(r7.kind, 'callExpression');
assert.equal(r7.comment, 'exportedExternalHoc1 comment');
assert.deepEqual(r7.callExpressionArguments, ['ExportedClass']);

// external hoc function
const r8 = result[7];
assert.equal(r8.name, 'exportedExternalHoc2');
assert.equal(r8.exported, true);
assert.equal(r8.type, 'exportedFunction');
assert.equal(r8.kind, 'callExpression');
assert.equal(r8.comment, 'exportedExternalHoc2 comment');
assert.deepEqual(r8.callExpressionArguments, ['exportedFunction']);
});

it('should provide data about interfaces', () => {
Expand Down
20 changes: 11 additions & 9 deletions src/getFileDocumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,28 @@ function isVarComponent(
function isHocClassComponent(entry: VariableEntry, classes: ClassEntry[]): boolean {
return entry.exported
&& entry.kind === 'callExpression'
&& entry.type !== null
// quick fix for external hoc - && entry.type !== null
&& entry.callExpressionArguments.length === 1
&& classes
.filter(i => isClassComponent(i, false))
.some(i => i.name === entry.type);
.some(i => i.name === entry.callExpressionArguments[0]);
}

function isVarClassComponent(
function isHocVarComponent(
entry: VariableEntry,
variables: VariableEntry[],
interfaces: InterfaceEntry[]): boolean {

return entry.exported
&& entry.kind === 'callExpression'
&& entry.type === '__function'
// quick fix for external hoc - && entry.type === '__function'
&& entry.callExpressionArguments.length === 1
&& variables
.filter(i => isVarComponent(i, interfaces, false))
.some(i => i.name === entry.callExpressionArguments[0]);
}


function getInterfaceDoc(entry: InterfaceEntry): InterfaceDoc {
return {
name: entry.name,
Expand Down Expand Up @@ -90,7 +92,7 @@ function getPropInterface(interfaces: InterfaceEntry[], propInterfaceName: strin
}
/** Generate documention for all classes in a set of .ts files */
export function getFileDocumentation(fileName: string, options: ts.CompilerOptions = defaultOptions): FileDoc {
const components: ComponentDoc[] = [];
const components: ComponentDoc[] = [];
let program = ts.createProgram([fileName], options);
let checker = program.getTypeChecker();
const model = transformAST(program.getSourceFile(fileName), checker);
Expand Down Expand Up @@ -119,24 +121,24 @@ export function getFileDocumentation(fileName: string, options: ts.CompilerOptio
.filter(i => isHocClassComponent(i, classes))
.map(i => ({
variable: i,
origin: classes.filter(c => c.name === i.type)[0]
origin: classes.filter(c => c.name === i.callExpressionArguments[0])[0]
}))
.map(i => ({
name: i.variable.name,
extends: i.variable.type,
extends: i.variable.callExpressionArguments[0],
comment: i.variable.comment || i.origin.comment,
propInterface: getClassPropInterface(interfaces, i.origin),
}));

const hocVarComponents = variables
.filter(i => isVarClassComponent(i, variables, interfaces))
.filter(i => isHocVarComponent(i, variables, interfaces))
.map(i => ({
variable: i,
origin: variables.filter(c => c.name === i.callExpressionArguments[0])[0]
}))
.map(i => ({
name: i.variable.name,
extends: i.variable.type,
extends: i.variable.callExpressionArguments[0],
comment: i.variable.comment || i.origin.comment,
propInterface: getVarPropInterface(interfaces, i.origin),
}));
Expand Down
4 changes: 2 additions & 2 deletions src/transformAST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function findAllNodes(rootNode: ts.Node, result: ts.Node[]) {
* Transform source file AST (abstract syntax tree) to our
* model (classes, interfaces, variables, methods).
*/
export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker) {
export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker) {
const nodes = [];
findAllNodes(sourceFile, nodes);

Expand Down Expand Up @@ -116,7 +116,7 @@ export function transformAST(sourceFile: ts.SourceFile, checker: ts.TypeChecker)
callExpressionArguments = callExpresson.arguments.map(i => i.getText());
}
}

return {
name: identifier.text,
exported: isNodeExported(i),
Expand Down
14 changes: 3 additions & 11 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
version "2.2.41"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"

"@types/node@^7.0.5":
"@types/node@^7.0.16":
version "7.0.16"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.16.tgz#e3440e3ce4d4931616ac418cc4dc16cd94b80092"

Expand Down Expand Up @@ -1592,14 +1592,10 @@ escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"

[email protected]:
[email protected], escape-string-regexp@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1"

escape-string-regexp@^1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"

esprima-fb@~15001.1001.0-dev-harmony-fb:
version "15001.1001.0-dev-harmony-fb"
resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz#43beb57ec26e8cf237d3dd8b33e42533577f2659"
Expand Down Expand Up @@ -3298,11 +3294,7 @@ randomatic@^1.1.3:
is-number "^2.0.2"
kind-of "^3.0.2"

range-parser@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"

range-parser@~1.0.3:
range-parser@^1.0.3, range-parser@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175"

Expand Down

0 comments on commit 2d90d95

Please sign in to comment.