Package Exports
- jsdoctypeparser
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (jsdoctypeparser) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
jsdoctypeparser
The parser can parse:
- JSDoc type expressions
foo.bar
,String[]
- Closure Compiler type expressions
Array<string>
,function(arg1, arg2): ret
- JSDuck type definitions
Boolean/"top"/"bottom"
- Complex type expressions
Array<Array<string>>
,function(function(Function))
Live demo
The live demo is available.
Usage
Parsing
var parse = require('jsdoctypeparser').parse;
var ast = parse('Array<MyClass>');
The ast
becomes:
{
"type": "GENERIC",
"subject": {
"type": "NAME",
"name": "Array"
},
"objects": [
{
"type": "NAME",
"name": "MyClass"
}
],
"meta": {
"syntax": "ANGLE_BRACKET"
}
}
See the AST specifications.
Publishing
We can stringify the AST nodes by using publish
.
var publish = require('jsdoctypeparser').publish;
var ast = {
type: 'GENERIC',
subject: {
type: 'NAME',
name: 'Array'
},
objects: [
{
type: 'NAME',
name: 'MyClass'
}
]
};
var string = publish(ast);
The string
becomes:
"Array<MyClass>"
Custom publishing
We can change the stringification strategy by using the 2nd parameter of publish(node, publisher)
.
The publisher
MUST have handlers for all node types (see lib/NodeType.js
).
And we can override default behavior by using createDefaultPublisher
.
const {publish, createDefaultPublisher} = require('jsdoctypeparser');
const ast = {
type: 'NAME',
name: 'MyClass',
};
const customPublisher = createDefaultPublisher();
customPublisher.NAME = (node, pub) =>
`<a href="./types/${node.name}.html">${node.name}</a>`;
const string = publish(ast, customPublisher);
The string
becomes:
<a href="./types/MyClass.html">MyClass</a>
Traversing
We can traverse the AST by using traverse
.
This function takes 3 parameters (a node and an onEnter handler, an onLeave handler).
The handlers take a visiting node.
const {parse, traverse} = require('jsdoctypeparser');
const ast = parse('Array<{ key1: function(), key2: A.B.C }>');
funciton onEnter(node) {
console.log('enter', node.type);
}
funciton onLeave(node) {
console.log('leave', node.type);
}
traverse(ast, onEnter, onLeave);
The output will be:
enter GENERIC
enter RECORD
enter RECORD_ENTRY
enter FUNCTION
leave FUNCTION
leave RECORD_ENTRY
enter RECORD_ENTRY
enter MEMBER
enter MEMBER
enter NAME
leave NAME
leave MEMBER
leave MEMBER
leave RECORD_ENTRY
leave RECORD
leave GENERIC
AST Specifications
NAME
Example:
/**
* @type {name}
*/
Structure:
{
"type": "NAME",
"name": string
}
MEMBER
Example:
/**
* @type {owner.name}
* @type {superOwner.owner.name}
*/
Structure:
{
"type": "MEMBER",
"name": string,
"owner": node
}
INNER_MEMBER
Example:
/**
* @type {owner~name}
*/
Structure:
{
"type": "INNER_MEMBER",
"name": string,
"owner": node
}
INSTANCE_MEMBER
Example:
/**
* @type {owner#name}
*/
Structure:
{
"type": "INSTANCE_MEMBER",
"name": string,
"owner": node
}
UNION
Example:
/**
* @type {left|right}
* @type {(left|right)}
* @type {left/right}
*/
Structure:
{
"type": "UNION",
"left": node,
"right": node,
"meta": {
"syntax": ("PIPE" or "SLASH")
}
}
RECORD
Example:
/**
* @type {{}}
* @type {{ key: value }}
* @type {{ key: value, anyKey }}
*/
Structure:
{
"type": "RECORD",
"entries": [
recordEntryNode,
recordEntryNode,
...
]
}
RECORD_ENTRY
Structure:
{
"type": "RECORD_ENTRY",
"key": string,
"value": node (or null)
}
GENERIC
Example:
/**
* @type {Subject<Object, Object>}
* @type {Object[]}
*/
Structure:
{
"type": "GENERIC",
"subject": node,
"objects": [
node,
node,
...
],
"meta": {
"syntax": ("ANGLE_BRACKET" or "ANGLE_BRACKET_WITH_DOT" or "SQUARE_BRACKET")
}
}
FUNCTION
Example:
/**
* @type {function()}
* @type {function(param, param): return}
* @type {function(this: Context)}
* @type {function(new: Class)}
*/
Structure:
{
"type": "FUNCTION",
"params": [
node,
node,
...
],
"returns": node (or null),
"new": node (or null),
"this": node (or null)
}
OPTIONAL
Example:
/**
* @type {Optional=}
*/
Structure:
{
"type": "OPTIONAL",
"value": node,
"meta": {
"syntax": ("PREFIX_EQUALS_SIGN" or "SUFFIX_EQUALS_SIGN")
}
}
NULLABLE
Example:
/**
* @type {?Nullable}
*/
Structure:
{
"type": "NULLABLE",
"value": node,
"meta": {
"syntax": ("PREFIX_QUESTION_MARK" or "SUFFIX_QUESTION_MARK")
}
}
NOT_NULLABLE
Example:
/**
* @type {!NotNullable}
*/
Structure:
{
"type": "NOT_NULLABLE",
"value": node,
"meta": {
"syntax": ("PREFIX_BANG" or "SUFFIX_BANG")
}
}
VARIADIC
Example:
/**
* @type {...Variadic}
* @type {Variadic...}
* @type {...}
*/
Structure:
{
"type": "VARIADIC",
"value": node (or null),
"meta": {
"syntax": ("PREFIX_DOTS" or "SUFFIX_DOTS" or "ONLY_DOTS")
}
}
MODULE
Example:
/**
* @type {module:path/to/file.Module}
*/
Structure:
{
"type": "MODULE",
"value": node
}
FILE_PATH
Example:
/**
* @type {module:path/to/file.Module}
* ^^^^^^^^^^^^
*/
Structure:
{
"type": "FILE_PATH",
"path": string
}
EXTERNAL
Example:
/**
* @type {external:External}
*/
Structure:
{
"type": "EXTERNAL",
"value": node
}
STRING_VALUE
Example:
/**
* @type {"abc"}
* @type {"can\"escape"}
*/
Structure:
{
"type": "STRING_VALUE",
"string": string
}
NUMBER_VALUE
Example:
/**
* @type {123}
* @type {0b11}
* @type {0o77}
* @type {0xff}
*/
Structure:
{
"type": "NUMBER_VALUE",
"number": string
}
ANY
Example:
/**
* @type {*}
*/
Structure:
{
"type": "ANY"
}
UNKNOWN
Example:
/**
* @type {?}
*/
Structure:
{
"type": "UNKNOWN"
}
PARENTHESIS
Example:
/**
* @type {(Foo)}
*/
Structure:
{
"type": "PARENTHESIS",
"value": node
}
Others
We can use a parenthesis to change operator orders.
/**
* @type {(module:path/to/file.js).foo}
*/