Skip to content

Commit

Permalink
docgen: Add support for TS exported static non-function variables (#3…
Browse files Browse the repository at this point in the history
…0971)

* docgen: Add support for TS exported static non-function variables

* Update CHANGELOG
  • Loading branch information
sarayourfriend authored Apr 20, 2021
1 parent 758aea8 commit 17b490a
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 4 deletions.
2 changes: 2 additions & 0 deletions packages/docgen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
### New Features

- Add support for array and object destructured arguments in TypeScript documentation generation.
- Add support for default arguments in TypeScript.
- Add support for static non-function variable type extraction in TypeScript.

## 1.16.0 (2021-03-17)

Expand Down
15 changes: 15 additions & 0 deletions packages/docgen/lib/get-jsdoc-from-token.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = ( token ) => {
} )[ 0 ];
if ( jsdoc ) {
let paramCount = 0;

jsdoc.tags = jsdoc.tags.map( ( tag ) => {
const isUnqualifiedParam =
tag.tag === 'param' && ! tag.name.includes( '.' );
Expand All @@ -40,6 +41,20 @@ module.exports = ( token ) => {
: tag.description,
};
} );

if ( jsdoc.tags.length === 0 ) {
const potentialTypeAnnotation = getTypeAnnotation(
{ tag: 'type' },
token,
0
);
if ( potentialTypeAnnotation !== '' ) {
jsdoc.tags.push( {
tag: 'type',
type: potentialTypeAnnotation,
} );
}
}
}
}
return jsdoc;
Expand Down
30 changes: 30 additions & 0 deletions packages/docgen/lib/get-type-annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,33 @@ function getReturnTypeAnnotation( declarationToken ) {
}
}

/**
* @param {ASTNode} declarationToken
* @return {string} The type annotation for the variable.
*/
function getVariableTypeAnnotation( declarationToken ) {
let resolvedToken = declarationToken;
if ( babelTypes.isExportNamedDeclaration( resolvedToken ) ) {
resolvedToken = resolvedToken.declaration;
}

if ( babelTypes.isClassDeclaration( resolvedToken ) ) {
// just use the classname if we're exporting a class
return resolvedToken.id.name;
}

if ( babelTypes.isVariableDeclaration( resolvedToken ) ) {
resolvedToken = resolvedToken.declarations[ 0 ].id;
}

try {
return getTypeAnnotation( resolvedToken.typeAnnotation.typeAnnotation );
} catch ( e ) {
// assume it's a fully undocumented variable, there's nothing we can do about that but fail silently.
return '';
}
}

module.exports =
/**
* @param {CommentTag} tag A comment tag.
Expand All @@ -531,6 +558,9 @@ module.exports =
case 'return': {
return getReturnTypeAnnotation( token );
}
case 'type': {
return getVariableTypeAnnotation( token );
}
default: {
return '';
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* This is a description of the variable
*/
export const foo: ( string | number )[] = [];
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
module.exports = () => ( {
type: 'ExportNamedDeclaration',
start: 49,
end: 94,
loc: {
start: {
line: 4,
column: 0,
},
end: {
line: 4,
column: 45,
},
},
leadingComments: [
{
type: 'CommentBlock',
value: '*\n * This is a description of the variable\n ',
start: 0,
end: 48,
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 3,
column: 3,
},
},
},
],
exportKind: 'value',
specifiers: [],
source: null,
declaration: {
type: 'VariableDeclaration',
start: 56,
end: 94,
loc: {
start: {
line: 4,
column: 7,
},
end: {
line: 4,
column: 45,
},
},
declarations: [
{
type: 'VariableDeclarator',
start: 62,
end: 93,
loc: {
start: {
line: 4,
column: 13,
},
end: {
line: 4,
column: 44,
},
},
id: {
type: 'Identifier',
start: 62,
end: 88,
loc: {
start: {
line: 4,
column: 13,
},
end: {
line: 4,
column: 39,
},
identifierName: 'foo',
},
name: 'foo',
typeAnnotation: {
type: 'TSTypeAnnotation',
start: 65,
end: 88,
loc: {
start: {
line: 4,
column: 16,
},
end: {
line: 4,
column: 39,
},
},
typeAnnotation: {
type: 'TSArrayType',
start: 67,
end: 88,
loc: {
start: {
line: 4,
column: 18,
},
end: {
line: 4,
column: 39,
},
},
elementType: {
type: 'TSParenthesizedType',
start: 67,
end: 86,
loc: {
start: {
line: 4,
column: 18,
},
end: {
line: 4,
column: 37,
},
},
typeAnnotation: {
type: 'TSUnionType',
start: 69,
end: 84,
loc: {
start: {
line: 4,
column: 20,
},
end: {
line: 4,
column: 35,
},
},
types: [
{
type: 'TSStringKeyword',
start: 69,
end: 75,
loc: {
start: {
line: 4,
column: 20,
},
end: {
line: 4,
column: 26,
},
},
},
{
type: 'TSNumberKeyword',
start: 78,
end: 84,
loc: {
start: {
line: 4,
column: 29,
},
end: {
line: 4,
column: 35,
},
},
},
],
},
},
},
},
},
init: {
type: 'ArrayExpression',
start: 91,
end: 93,
loc: {
start: {
line: 4,
column: 42,
},
end: {
line: 4,
column: 44,
},
},
elements: [],
},
},
],
kind: 'const',
},
} );
29 changes: 25 additions & 4 deletions packages/docgen/test/get-intermediate-representation.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ describe( 'Intermediate Representation', () => {
lineEnd: 4,
} );
} );

it( 'named export', () => {
const tokenClass = fs.readFileSync(
path.join( __dirname, './fixtures/named-class/exports.json' ),
Expand All @@ -165,7 +166,12 @@ describe( 'Intermediate Representation', () => {
path: null,
name: 'MyDeclaration',
description: 'My declaration example.',
tags: [],
tags: [
{
tag: 'type',
type: 'MyDeclaration',
},
],
lineStart: 4,
lineEnd: 4,
} );
Expand Down Expand Up @@ -266,7 +272,12 @@ describe( 'Intermediate Representation', () => {
path: null,
name: 'default',
description: 'Class declaration example.',
tags: [],
tags: [
{
tag: 'type',
type: 'ClassDeclaration',
},
],
lineStart: 6,
lineEnd: 6,
} );
Expand Down Expand Up @@ -404,7 +415,12 @@ describe( 'Intermediate Representation', () => {
path: null,
name: 'ClassDeclaration',
description: 'Class declaration example.',
tags: [],
tags: [
{
tag: 'type',
type: 'ClassDeclaration',
},
],
lineStart: 16,
lineEnd: 16,
} );
Expand Down Expand Up @@ -440,7 +456,12 @@ describe( 'Intermediate Representation', () => {
path: null,
name: 'ClassDeclaration',
description: 'Class declaration example.',
tags: [],
tags: [
{
tag: 'type',
type: 'ClassDeclaration',
},
],
lineStart: 11,
lineEnd: 11,
} );
Expand Down
11 changes: 11 additions & 0 deletions packages/docgen/test/get-type-annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const getArrayDestructuringTupleTypeNode = require( './fixtures/type-annotations
const getArrayDestructuringAnyOtherTypeNode = require( './fixtures/type-annotations/array-destructuring-any-other-type/get-node' );
const getObjectDestructuringTypeLiteralNode = require( './fixtures/type-annotations/object-destructuring-object-literal-type/get-node' );
const getAssignmentPatternNode = require( './fixtures/type-annotations/assignment-pattern/get-node' );
const getExportedVariableDeclarationStaticNode = require( './fixtures/type-annotations/exported-variable-declaration-statics/get-node' );

describe( 'Type annotations', () => {
it( 'are taken from JSDoc if any', () => {
Expand Down Expand Up @@ -311,4 +312,14 @@ describe( 'Type annotations', () => {
).toBe( '( string )[ 0 ]' );
} );
} );

describe( 'static exported variable', () => {
const node = getExportedVariableDeclarationStaticNode();

it( 'should get the type of the variable', () => {
expect( getTypeAnnotation( { tag: 'type' }, node, 0 ) ).toBe(
'( string | number )[]'
);
} );
} );
} );

0 comments on commit 17b490a

Please sign in to comment.