Socket
Socket
Sign inDemoInstall

jsdoctypeparser

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsdoctypeparser - npm Package Compare versions

Comparing version 4.0.0 to 5.0.0

tsconfig.json

4

index.js
'use strict';
const {parse, SyntaxError} = require('./lib/parsing.js');
const {parse, JSDocTypeSyntaxError} = require('./lib/parsing.js');
const {publish, createDefaultPublisher} = require('./lib/publishing.js');

@@ -17,3 +17,3 @@ const {traverse} = require('./lib/traversing.js');

parse,
SyntaxError,
JSDocTypeSyntaxError,
publish,

@@ -20,0 +20,0 @@ createDefaultPublisher,

@@ -29,5 +29,8 @@ 'use strict';

TYPE_QUERY: 'TYPE_QUERY',
KEY_QUERY: 'KEY_QUERY',
IMPORT: 'IMPORT',
};
module.exports = NodeType;
/** @typedef {keyof typeof NodeType} Type */
module.exports = /** @type {{readonly [T in Type]: T}} */ (NodeType);
'use strict';
const {SyntaxError, parse} = require('../peg_lib/jsdoctype.js');
const {SyntaxError: JSDocTypeSyntaxError, parse} = require('../peg_lib/jsdoctype.js');

@@ -11,3 +11,3 @@ module.exports = {

*/
SyntaxError,
JSDocTypeSyntaxError,

@@ -14,0 +14,0 @@

@@ -5,2 +5,10 @@ 'use strict';

/** @typedef {(node) => string} ConcretePublish */
/** @typedef {{ [T in import('./NodeType').Type]: (node, publish: ConcretePublish) => string }} Publisher */
/**
* @param node
* @param {Publisher} [opt_publisher]
* @return {string}
*/
function publish(node, opt_publisher) {

@@ -13,3 +21,29 @@ const publisher = opt_publisher || createDefaultPublisher();

/**
* @private
* @param {string} str
* @param {boolean} quoteStyle
* @returns {str} Formatted string
*/
function addQuotesForName (str, quoteStyle) {
// For `MemberName`, not strings
if (!quoteStyle || quoteStyle === 'none') {
return str;
}
const singleQuoteStyle = quoteStyle === 'single';
return format(
singleQuoteStyle
? "'%s'"
: '"%s"',
str
.replace(/\\/g, '\\\\')
.replace(
singleQuoteStyle ? /'/gu : /"/gu,
'\\' + (singleQuoteStyle ? "'" : '"')
)
);
}
/** @return {Publisher} */
function createDefaultPublisher() {

@@ -23,3 +57,3 @@ return {

memberNode.hasEventPrefix ? 'event:' : '',
memberNode.name);
addQuotesForName(memberNode.name, memberNode.quoteStyle));
},

@@ -38,4 +72,4 @@ UNION (unionNode, concretePublish) {

RECORD_ENTRY (entryNode, concretePublish) {
if (!entryNode.value) return entryNode.key;
return format('%s: %s', entryNode.key, concretePublish(entryNode.value));
if (!entryNode.value) return addQuotesForName(entryNode.key, entryNode.quoteStyle);
return format('%s: %s', addQuotesForName(entryNode.key, entryNode.quoteStyle), concretePublish(entryNode.value));
},

@@ -67,3 +101,3 @@ TUPLE (tupleNode, concretePublish) {

FILE_PATH (filePathNode) {
return filePathNode.path;
return addQuotesForName(filePathNode.path, filePathNode.quoteStyle);
},

@@ -114,10 +148,12 @@ OPTIONAL (optionalNode, concretePublish) {

return concretePublish(memberNode.owner) + '~' +
(memberNode.hasEventPrefix ? 'event:' : '') + memberNode.name;
(memberNode.hasEventPrefix ? 'event:' : '') +
addQuotesForName(memberNode.name, memberNode.quoteStyle);
},
INSTANCE_MEMBER (memberNode, concretePublish) {
return concretePublish(memberNode.owner) + '#' +
(memberNode.hasEventPrefix ? 'event:' : '') + memberNode.name;
(memberNode.hasEventPrefix ? 'event:' : '') +
addQuotesForName(memberNode.name, memberNode.quoteStyle);
},
STRING_VALUE (stringValueNode) {
return format('"%s"', stringValueNode.string);
return addQuotesForName(stringValueNode.string, stringValueNode.quoteStyle)
},

@@ -128,3 +164,4 @@ NUMBER_VALUE (numberValueNode) {

EXTERNAL (externalNode, concretePublish) {
return format('external:%s', concretePublish(externalNode.value));
const {name, quoteStyle} = externalNode;
return format('external:%s', addQuotesForName(name, quoteStyle));
},

@@ -137,2 +174,5 @@ PARENTHESIS (parenthesizedNode, concretePublish) {

},
KEY_QUERY (keyQueryNode, concretePublish) {
return format('keyof %s', concretePublish(keyQueryNode.value));
},
IMPORT (importNode, concretePublish) {

@@ -139,0 +179,0 @@ return format('import(%s)', concretePublish(importNode.path));

'use strict';
/** @typedef {import('./NodeType').Type} NodeType */
/** @typedef {{ type: NodeType }} Node */
/** @typedef {(node: Node, parentPropName: string | null, parentNode: Node | null) => void} TraversalCallback */
/**
* Traverse the specified AST.
* @param {{ type: NodeType }} node AST to traverse.
* @param {function({ type: NodeType })?} opt_onEnter Callback for onEnter.
* @param {function({ type: NodeType })?} opt_onLeave Callback for onLeave.
* @param {Node} node AST to traverse.
* @param {TraversalCallback} [opt_onEnter] Callback for onEnter.
* @param {TraversalCallback} [opt_onLeave] Callback for onLeave.
*/

@@ -43,3 +47,6 @@ function traverse(node, opt_onEnter, opt_onLeave) {

/** @private */
/**
* @private
* @type {{ [T in NodeType]: object }}
*/
const _childNodesMap = {

@@ -116,2 +123,5 @@ NAME: {},

},
KEY_QUERY: {
value: _PropertyAccessor.NODE,
},
IMPORT: {

@@ -123,3 +133,6 @@ path: _PropertyAccessor.NODE,

/** @private */
/**
* @private
* @param {Node} node
*/
function _collectChildNodeInfo(node) {

@@ -126,0 +139,0 @@ const childNodeInfo = [];

{
"name": "jsdoctypeparser",
"description": "Strict JsDoc type expression parser.",
"version": "4.0.0",
"version": "5.0.0",
"author": "Kuniwak <orga.chem.job@gmail.com>",

@@ -22,3 +22,3 @@ "contributors": [

},
"homepage": "https://jsdoctypeparser.github.io/jsdoctypeparser/",
"homepage": "https://jsdoctypeparser.github.io",
"bugs": {

@@ -32,2 +32,3 @@ "mail": "orga.chem.job@gmail.com",

"main": "index.js",
"bin": "./bin/jsdoctypeparser",
"scripts": {

@@ -43,14 +44,15 @@ "prepare": "npm-run-all build",

},
"readmeFilename": "README.md",
"dependencies": {},
"devDependencies": {
"@types/node": "^12.0.10",
"chai": "^4.2.0",
"eslint": "^5.16.0",
"eslint": "^6.0.1",
"mkdirp": "^0.5.1",
"mocha": "^6.1.4",
"npm-run-all": "^4.1.5",
"object.entries-ponyfill": "^1.0.1",
"pegjs": "^0.10.0",
"rimraf": "^2.6.3"
},
"license": "MIT",
"dependencies": {}
"license": "MIT"
}

@@ -8,3 +8,3 @@ # jsdoctypeparser

* [JSDoc type expressions](http://usejsdoc.org/tags-type.html)
* [JSDoc type expressions](https://jsdoc.app/tags-type.html)
* `foo.bar`, `String[]`

@@ -22,5 +22,5 @@ * [Closure Compiler type expressions](https://developers.google.com/closure/compiler/docs/js-for-compiler)

The [live demo](https://jsdoctypeparser.github.io/jsdoctypeparser/) is available.
The [live demo](https://jsdoctypeparser.github.io) is available.
## Usage
## Usage (Programmatic)

@@ -198,2 +198,3 @@ ### Parsing

"name": string,
"quoteStyle": "none",
"owner": node,

@@ -220,2 +221,3 @@ "hasEventPrefix": boolean

"name": string,
"quoteStyle": "none",
"owner": node,

@@ -242,2 +244,3 @@ "hasEventPrefix": boolean

"name": string,
"quoteStyle": "none",
"owner": node,

@@ -531,2 +534,3 @@ "hasEventPrefix": boolean

"type": "STRING_VALUE",
"quoteStyle": "double",
"string": string

@@ -623,4 +627,18 @@ }

## Usage (CLI)
To parse a type into a JSON structure, you may pass a string argument
containing the structure to parse (with the JSON results equivalent to the
parsing example above):
```
jsdoctypeparser 'Array<MyClass>'
```
Note: There is no need to prefix the path to the `jsdoctypeparser` binary,
e.g., with `./node_modules/.bin/` when you are running within one of the
`package.json` `scripts` or if you have installed the package globally.
## License
[This script is licensed under the MIT](./LICENSE-MIT.txt).

@@ -6,3 +6,8 @@ {

"owner": { "$ref": "Node.json" },
"name": { "type": "string" }
"name": { "type": "string" },
"hasEventPrefix": { "type": "boolean" },
"quoteStyle": {
"type": "string",
"enum": ["single", "double", "none"]
}
},

@@ -9,0 +14,0 @@ "required": [

@@ -6,3 +6,8 @@ {

"owner": { "$ref": "Node.json" },
"name": { "type": "string" }
"name": { "type": "string" },
"hasEventPrefix": { "type": "boolean" },
"quoteStyle": {
"type": "string",
"enum": ["single", "double", "none"]
}
},

@@ -9,0 +14,0 @@ "required": [

@@ -6,3 +6,8 @@ {

"owner": { "$ref": "Node.json" },
"name": { "type": "string" }
"name": { "type": "string" },
"hasEventPrefix": { "type": "boolean" },
"quoteStyle": {
"type": "string",
"enum": ["single", "double", "none"]
}
},

@@ -9,0 +14,0 @@ "required": [

@@ -5,3 +5,7 @@ {

"type": { "$ref": "NodeType.json" },
"string": { "type": "string" }
"string": { "type": "string" },
"quoteStyle": {
"type": "string",
"enum": ["single", "double", "none"]
}
},

@@ -8,0 +12,0 @@ "required": [

@@ -9,3 +9,3 @@ 'use strict';

parse: 'function',
SyntaxError: 'function',
JSDocTypeSyntaxError: 'function',
publish: 'function',

@@ -12,0 +12,0 @@ createDefaultPublisher: 'function',

'use strict';
const {expect, assert} = require('chai');
const {expect} = require('chai');

@@ -9,2 +9,4 @@ const NodeType = require('../lib/NodeType.js');

/** @typedef {{type: import('../lib/NodeType').Type}} Node */
const {

@@ -16,1352 +18,1689 @@ GenericTypeSyntax, UnionTypeSyntax, VariadicTypeSyntax,

describe('Parser', function() {
it('should return a type name node when "TypeName" arrived', function() {
const typeExprStr = 'TypeName';
const node = Parser.parse(typeExprStr);
describe('Primitive types', function () {
it('should return a number value type node when "0123456789" arrived', function() {
const typeExprStr = '0123456789';
const node = Parser.parse(typeExprStr);
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a type name node when "my-type" arrived', function() {
const typeExprStr = 'my-type';
const node = Parser.parse(typeExprStr);
it('should return a number value type node when "0.0" arrived', function() {
const typeExprStr = '0.0';
const node = Parser.parse(typeExprStr);
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when ".0" arrived', function() {
const typeExprStr = '.0';
const node = Parser.parse(typeExprStr);
it('should return a type name node when "$" arrived', function() {
const typeExprStr = '$';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "-0" arrived', function() {
const typeExprStr = '-0';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a type name node when "_" arrived', function() {
const typeExprStr = '_';
const node = Parser.parse(typeExprStr);
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "+0" arrived', function() {
const typeExprStr = '+0';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return an any type node when "*" arrived', function() {
const typeExprStr = '*';
const node = Parser.parse(typeExprStr);
it('should return a number value type node when "3e5" arrived', function() {
const typeExprStr = '3e5';
const node = Parser.parse(typeExprStr);
const expectedNode = createAnyTypeNode();
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "3e+5" arrived', function() {
const typeExprStr = '3e+5';
const node = Parser.parse(typeExprStr);
it('should return an unknown type node when "?" arrived', function() {
const typeExprStr = '?';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createUnknownTypeNode();
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "3e-5" arrived', function() {
const typeExprStr = '3e-5';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional unknown type node when "?=" arrived', function() {
const typeExprStr = '?=';
const node = Parser.parse(typeExprStr);
it('should return a number value type node when "3.14e5" arrived', function() {
const typeExprStr = '3.14e5';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createUnknownTypeNode(),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0b01" arrived', function() {
const typeExprStr = '0b01';
const node = Parser.parse(typeExprStr);
it('should return a module name node when "module:path/to/file" arrived', function() {
const typeExprStr = 'module:path/to/file';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(createFilePathNode('path/to/file'));
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0o01234567" arrived', function() {
const typeExprStr = '0o01234567';
const node = Parser.parse(typeExprStr);
it('should return a module name node when "module : path/to/file" arrived', function() {
const typeExprStr = 'module : path/to/file';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(createFilePathNode('path/to/file'));
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0x0123456789abcdef" arrived', function() {
const typeExprStr = '0x0123456789abcdef';
const node = Parser.parse(typeExprStr);
it('should return a member node when "(module:path/to/file).member" arrived', function() {
const typeExprStr = '(module:path/to/file).member';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createParenthesizedNode(
createModuleNameNode(createFilePathNode('path/to/file'))
),
'member'
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a string value type node when \'""\' arrived', function() {
const typeExprStr = '""';
const node = Parser.parse(typeExprStr);
it('should return a member node when "module:path/to/file.member" arrived', function() {
const typeExprStr = 'module:path/to/file.member';
const node = Parser.parse(typeExprStr);
const expectedNode = createStringValueNode('');
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path/to/file'), 'member')
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a string value type node when "\'\'" arrived', function() {
const typeExprStr = "''";
const node = Parser.parse(typeExprStr);
it('should return a member node when "module:path/to/file.event:member" arrived', function() {
const typeExprStr = 'module:path/to/file.event:member';
const node = Parser.parse(typeExprStr);
const expectedNode = createStringValueNode('', 'single');
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path/to/file'), 'member', true)
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a member type node when "owner.event:Member" arrived', function() {
const typeExprStr = 'owner.event:Member';
const node = Parser.parse(typeExprStr);
it('should return a string value type node when \'"string"\' arrived', function() {
const typeExprStr = '"string"';
const node = Parser.parse(typeExprStr);
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Member',
true);
const expectedNode = createStringValueNode('string');
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a module name node when "external:string" arrived', function() {
const typeExprStr = 'external:string';
const node = Parser.parse(typeExprStr);
it('should return a string value type node when \'"マルチバイト"\' arrived', function() {
const typeExprStr = '"マルチバイト"';
const node = Parser.parse(typeExprStr);
const expectedNode = createExternalNameNode(createTypeNameNode('string'));
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createStringValueNode('マルチバイト');
expect(node).to.deep.equal(expectedNode);
});
it('should return a module name node when "external : String#rot13" arrived', function() {
const typeExprStr = 'external : String#rot13';
const node = Parser.parse(typeExprStr);
it('should return a string value type node when \'"\\n\\"\\t"\' arrived', function() {
const typeExprStr = '"\\n\\"\\t"';
const node = Parser.parse(typeExprStr);
const expectedNode = createExternalNameNode(
createInstanceMemberTypeNode(createTypeNameNode('String'), 'rot13'));
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createStringValueNode('\\n"\\t');
expect(node).to.deep.equal(expectedNode);
});
it('should return a string value type node when \'"\\string with\\ \\"escapes\\\\"\' arrived', function() {
const typeExprStr = '"\\string with\\ \\"escapes\\\\"';
const node = Parser.parse(typeExprStr);
it('should return a member type node when "owner.Member" arrived', function() {
const typeExprStr = 'owner.Member';
const node = Parser.parse(typeExprStr);
const expectedNode = createStringValueNode('\\string with\\ "escapes\\');
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Member');
it('should throw for string value type node with unescaped quotes', function() {
const typeExprStr = '"string with "unescaped quote"';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('or end of input but "u" found.');
});
expect(node).to.deep.equal(expectedNode);
});
it('should throw for string value type node with unescaped quotes (preceded by escaped backslash)', function() {
const typeExprStr = '"string with \\\\"unescaped quote"';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('or end of input but "u" found.');
});
it('should return a member type node when "owner . Member" arrived', function() {
const typeExprStr = 'owner . Member';
const node = Parser.parse(typeExprStr);
it('should throw a syntax error when "" arrived', function() {
const typeExprStr = '';
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Member');
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
expect(node).to.deep.equal(expectedNode);
it('should throw a syntax error when "Invalid type" arrived', function() {
const typeExprStr = 'Invalid type';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
});
describe('Wildcard types', function () {
it('should return an any type node when "*" arrived', function() {
const typeExprStr = '*';
const node = Parser.parse(typeExprStr);
it('should return a member type node when "superOwner.owner.Member" arrived', function() {
const typeExprStr = 'superOwner.owner.Member';
const node = Parser.parse(typeExprStr);
const expectedNode = createAnyTypeNode();
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createMemberTypeNode(
createTypeNameNode('superOwner'), 'owner'),
'Member');
expect(node).to.deep.equal(expectedNode);
it('should return an unknown type node when "?" arrived', function() {
const typeExprStr = '?';
const node = Parser.parse(typeExprStr);
const expectedNode = createUnknownTypeNode();
expect(node).to.deep.equal(expectedNode);
});
});
describe('Generic types', function () {
it('should return a generic type node when "[][]" arrived', function() {
const typeExprStr = '[][]';
const node = Parser.parse(typeExprStr);
it('should return a member type node when "superOwner.owner.Member=" arrived', function() {
const typeExprStr = 'superOwner.owner.Member=';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'),
[
createTupleTypeNode([]),
],
GenericTypeSyntax.SQUARE_BRACKET);
const expectedNode = createOptionalTypeNode(
createMemberTypeNode(
createMemberTypeNode(
createTypeNameNode('superOwner'),
'owner'),
'Member'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "[TupleType][]" arrived', function() {
const typeExprStr = '[TupleType][]';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'),
[
createTupleTypeNode([
createTypeNameNode('TupleType'),
]),
],
GenericTypeSyntax.SQUARE_BRACKET);
it('should return an inner member type node when "owner~innerMember" arrived', function() {
const typeExprStr = 'owner~innerMember';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createInnerMemberTypeNode(
createTypeNameNode('owner'),
'innerMember');
it('should return a generic type node when "[TupleType1, TupleType2][]" arrived', function() {
const typeExprStr = '[TupleType1, TupleType2][]';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'),
[
createTupleTypeNode([
createTypeNameNode('TupleType1'),
createTypeNameNode('TupleType2'),
]),
],
GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an inner member type node when "owner ~ innerMember" arrived', function() {
const typeExprStr = 'owner ~ innerMember';
const node = Parser.parse(typeExprStr);
const expectedNode = createInnerMemberTypeNode(
createTypeNameNode('owner'),
'innerMember');
it('should return a generic type node when "Generic<ParamType>" arrived', function() {
const typeExprStr = 'Generic<ParamType>';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.ANGLE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an inner member type node when "superOwner~owner~innerMember" ' +
'arrived', function() {
const typeExprStr = 'superOwner~owner~innerMember';
const node = Parser.parse(typeExprStr);
const expectedNode = createInnerMemberTypeNode(
createInnerMemberTypeNode(
createTypeNameNode('superOwner'), 'owner'),
'innerMember');
it('should return a generic type node when "Generic<Inner<ParamType>>" arrived', function() {
const typeExprStr = 'Generic<Inner<ParamType>>';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createGenericTypeNode(
createTypeNameNode('Inner'), [ createTypeNameNode('ParamType') ]
),
], GenericTypeSyntax.ANGLE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an inner member type node when "superOwner~owner~innerMember=" ' +
'arrived', function() {
const typeExprStr = 'superOwner~owner~innerMember=';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createInnerMemberTypeNode(
createInnerMemberTypeNode(
createTypeNameNode('superOwner'),
'owner'),
'innerMember'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return a generic type node when "Generic<ParamType1,ParamType2>"' +
' arrived', function() {
const typeExprStr = 'Generic<ParamType1,ParamType2>';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an instance member type node when "owner#instanceMember" arrived', function() {
const typeExprStr = 'owner#instanceMember';
const node = Parser.parse(typeExprStr);
const expectedNode = createInstanceMemberTypeNode(
createTypeNameNode('owner'),
'instanceMember');
it('should return a generic type node when "Generic < ParamType1 , ParamType2 >"' +
' arrived', function() {
const typeExprStr = 'Generic < ParamType1, ParamType2 >';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an instance member type node when "owner # instanceMember" ' +
'arrived', function() {
const typeExprStr = 'owner # instanceMember';
const node = Parser.parse(typeExprStr);
const expectedNode = createInstanceMemberTypeNode(
createTypeNameNode('owner'),
'instanceMember');
it('should return a generic type node when "Generic.<ParamType>" arrived', function() {
const typeExprStr = 'Generic.<ParamType>';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.ANGLE_BRACKET_WITH_DOT);
expect(node).to.deep.equal(expectedNode);
});
it('should return an instance member type node when "superOwner#owner#instanceMember" ' +
'arrived', function() {
const typeExprStr = 'superOwner#owner#instanceMember';
const node = Parser.parse(typeExprStr);
const expectedNode = createInstanceMemberTypeNode(
createInstanceMemberTypeNode(
createTypeNameNode('superOwner'), 'owner'),
'instanceMember');
it('should return a generic type node when "Generic.<ParamType1,ParamType2>"' +
' arrived', function() {
const typeExprStr = 'Generic.<ParamType1,ParamType2>';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET_WITH_DOT);
expect(node).to.deep.equal(expectedNode);
});
it('should return an instance member type node when "superOwner#owner#instanceMember=" ' +
'arrived', function() {
const typeExprStr = 'superOwner#owner#instanceMember=';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createInstanceMemberTypeNode(
createInstanceMemberTypeNode(
createTypeNameNode('superOwner'),
'owner'),
'instanceMember'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return a generic type node when "Generic .< ParamType1 , ParamType2 >"' +
' arrived', function() {
const typeExprStr = 'Generic .< ParamType1 , ParamType2 >';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET_WITH_DOT);
expect(node).to.deep.equal(expectedNode);
});
it('should return an union type when "LeftType|RightType" arrived', function() {
const typeExprStr = 'LeftType|RightType';
const node = Parser.parse(typeExprStr);
const expectedNode = createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType'),
UnionTypeSyntax.PIPE
);
it('should return a generic type node when "ParamType[]" arrived', function() {
const typeExprStr = 'ParamType[]';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an union type when "LeftType|MiddleType|RightType" arrived', function() {
const typeExprStr = 'LeftType|MiddleType|RightType';
const node = Parser.parse(typeExprStr);
const expectedNode = createUnionTypeNode(
createTypeNameNode('LeftType'),
createUnionTypeNode(
createTypeNameNode('MiddleType'),
createTypeNameNode('RightType'),
UnionTypeSyntax.PIPE
), UnionTypeSyntax.PIPE);
it('should return a generic type node when "ParamType[][]" arrived', function() {
const typeExprStr = 'ParamType[][]';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'), [
createGenericTypeNode(
createTypeNameNode('Array'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.SQUARE_BRACKET),
], GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return an union type when "(LeftType|RightType)" arrived', function() {
const typeExprStr = '(LeftType|RightType)';
const node = Parser.parse(typeExprStr);
const expectedNode = createParenthesizedNode(
createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType')
)
);
it('should return a generic type node when "ParamType [ ] [ ]" arrived', function() {
const typeExprStr = 'ParamType [ ] [ ]';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'), [
createGenericTypeNode(
createTypeNameNode('Array'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.SQUARE_BRACKET),
], GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should throw a syntax error when "Promise*Error" arrived', function() {
const typeExprStr = 'Promise*Error';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
});
describe('Record types', function () {
it('should return a record type node when "{}" arrived', function() {
const typeExprStr = '{}';
const node = Parser.parse(typeExprStr);
it('should return an union type when "( LeftType | RightType )" arrived', function() {
const typeExprStr = '( LeftType | RightType )';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([]);
const expectedNode = createParenthesizedNode(
createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType')
)
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when "{key:ValueType}" arrived', function() {
const typeExprStr = '{key:ValueType}';
const node = Parser.parse(typeExprStr);
it('should return an union type when "LeftType/RightType" arrived', function() {
const typeExprStr = 'LeftType/RightType';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key', createTypeNameNode('ValueType')),
]);
const expectedNode = createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType'),
UnionTypeSyntax.SLASH
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when "{keyOnly}" arrived', function() {
const typeExprStr = '{keyOnly}';
const node = Parser.parse(typeExprStr);
it('should return a record type node when "{}" arrived', function() {
const typeExprStr = '{}';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('keyOnly', null),
]);
const expectedNode = createRecordTypeNode([]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when \'{"keyOnly"}\' arrived', function() {
const typeExprStr = '{"keyOnly"}';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('keyOnly', null, 'double'),
]);
it('should return a record type node when "{key:ValueType}" arrived', function() {
const typeExprStr = '{key:ValueType}';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key', createTypeNameNode('ValueType')),
]);
it('should return a record type node when "{\'keyOnly\'}" arrived', function() {
const typeExprStr = "{'keyOnly'}";
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createRecordTypeNode([
createRecordEntryNode('keyOnly', null, 'single'),
]);
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when "{keyOnly}" arrived', function() {
const typeExprStr = '{keyOnly}';
const node = Parser.parse(typeExprStr);
it('should return a record type node when \'{"ke\\\\y\\Only\\""}\' arrived', function() {
const typeExprStr = '{"ke\\\\y\\Only\\""}';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('keyOnly', null),
]);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('ke\\y\\Only"', null, 'double'),
]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should throw when \'{"key"Only"}\' arrived', function() {
const typeExprStr = '{"key"Only"}';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('Expected ",", ":", "}", or [ \\t\\r\\n ] but "O" found.');
});
it('should return a record type node when "{key1:ValueType1,key2:ValueType2}"' +
' arrived', function() {
const typeExprStr = '{key1:ValueType1,key2:ValueType2}';
const node = Parser.parse(typeExprStr);
it('should throw when \'{"key\\\\"Only"}\' arrived', function() {
const typeExprStr = '{"key\\\\"Only"}';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('Expected ",", ":", "}", or [ \\t\\r\\n ] but "O" found.');
});
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key1', createTypeNameNode('ValueType1')),
createRecordEntryNode('key2', createTypeNameNode('ValueType2')),
]);
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when "{key1:ValueType1,key2:ValueType2}"' +
' arrived', function() {
const typeExprStr = '{key1:ValueType1,key2:ValueType2}';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key1', createTypeNameNode('ValueType1')),
createRecordEntryNode('key2', createTypeNameNode('ValueType2')),
]);
it('should return a record type node when "{key:ValueType1,keyOnly}"' +
' arrived', function() {
const typeExprStr = '{key:ValueType1,keyOnly}';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key', createTypeNameNode('ValueType1')),
createRecordEntryNode('keyOnly', null),
]);
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when "{key:ValueType1,keyOnly}"' +
' arrived', function() {
const typeExprStr = '{key:ValueType1,keyOnly}';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key', createTypeNameNode('ValueType1')),
createRecordEntryNode('keyOnly', null),
]);
it('should return a record type node when "{ key1 : ValueType1 , key2 : ValueType2 }"' +
' arrived', function() {
const typeExprStr = '{ key1 : ValueType1 , key2 : ValueType2 }';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key1', createTypeNameNode('ValueType1')),
createRecordEntryNode('key2', createTypeNameNode('ValueType2')),
]);
expect(node).to.deep.equal(expectedNode);
});
it('should return a record type node when "{ key1 : ValueType1 , key2 : ValueType2 }"' +
' arrived', function() {
const typeExprStr = '{ key1 : ValueType1 , key2 : ValueType2 }';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('key1', createTypeNameNode('ValueType1')),
createRecordEntryNode('key2', createTypeNameNode('ValueType2')),
]);
it('should return a record type node when "{\'quoted-key\':ValueType}"' +
' arrived', function() {
const typeExprStr = '{\'quoted-key\':ValueType}';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createRecordTypeNode([
createRecordEntryNode('quoted-key', createTypeNameNode('ValueType')),
]);
expect(node).to.deep.equal(expectedNode);
it('should return a record type node when "{\'quoted-key\':ValueType}"' +
' arrived', function() {
const typeExprStr = '{\'quoted-key\':ValueType}';
const node = Parser.parse(typeExprStr);
const expectedNode = createRecordTypeNode([
createRecordEntryNode('quoted-key', createTypeNameNode('ValueType'), 'single'),
]);
expect(node).to.deep.equal(expectedNode);
});
});
describe('Tuple types', function () {
it('should return a tuple type node when "[]" arrived', function() {
const typeExprStr = '[]';
const node = Parser.parse(typeExprStr);
it('should return a tuple type node when "[]" arrived', function() {
const typeExprStr = '[]';
const node = Parser.parse(typeExprStr);
const expectedNode = createTupleTypeNode([]);
const expectedNode = createTupleTypeNode([]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a tuple type node when "[TupleType]" arrived', function() {
const typeExprStr = '[TupleType]';
const node = Parser.parse(typeExprStr);
it('should return a tuple type node when "[TupleType]" arrived', function() {
const typeExprStr = '[TupleType]';
const node = Parser.parse(typeExprStr);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleType'),
]);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleType'),
]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a tuple type node when "[TupleType1, TupleType2]" arrived', function() {
const typeExprStr = '[TupleType1, TupleType2]';
const node = Parser.parse(typeExprStr);
it('should return a tuple type node when "[TupleType1, TupleType2]" arrived', function() {
const typeExprStr = '[TupleType1, TupleType2]';
const node = Parser.parse(typeExprStr);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleType1'),
createTypeNameNode('TupleType2'),
]);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleType1'),
createTypeNameNode('TupleType2'),
]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a tuple type node when "[TupleConcreteType, ...TupleVarargsType]" arrived', function() {
const typeExprStr = '[TupleConcreteType, ...TupleVarargsType]';
const node = Parser.parse(typeExprStr);
it('should return a tuple type node when "[TupleConcreteType, ...TupleVarargsType]" arrived', function() {
const typeExprStr = '[TupleConcreteType, ...TupleVarargsType]';
const node = Parser.parse(typeExprStr);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleConcreteType'),
createVariadicTypeNode(
createTypeNameNode('TupleVarargsType'),
VariadicTypeSyntax.PREFIX_DOTS
),
]);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleConcreteType'),
createVariadicTypeNode(
createTypeNameNode('TupleVarargsType'),
VariadicTypeSyntax.PREFIX_DOTS
),
]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a tuple type node when "[TupleConcreteType, TupleBrokenVarargsType...]" arrived', function() {
const typeExprStr = '[TupleConcreteType, TupleBrokenVarargsType...]';
const node = Parser.parse(typeExprStr);
it('should return a tuple type node when "[TupleConcreteType, TupleBrokenVarargsType...]" arrived', function() {
const typeExprStr = '[TupleConcreteType, TupleBrokenVarargsType...]';
const node = Parser.parse(typeExprStr);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleConcreteType'),
createVariadicTypeNode(
// This is broken because the TypeScript JSDoc parser doesn't support
// the suffix dots variadic type syntax:
createTypeNameNode('TupleBrokenVarargsType'),
VariadicTypeSyntax.SUFFIX_DOTS
),
]);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleConcreteType'),
createVariadicTypeNode(
// This is broken because the TypeScript JSDoc parser doesn't support
// the suffix dots variadic type syntax:
createTypeNameNode('TupleBrokenVarargsType'),
VariadicTypeSyntax.SUFFIX_DOTS
),
]);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
it('should return a tuple type node when "[TupleAnyVarargs, ...]" arrived', function() {
const typeExprStr = '[TupleAnyVarargs, ...]';
const node = Parser.parse(typeExprStr);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleAnyVarargs'),
createVariadicTypeNode(
null,
VariadicTypeSyntax.ONLY_DOTS
),
]);
expect(node).to.deep.equal(expectedNode);
});
});
describe('Function/Constructor/Arrow types', function () {
it('should return a function type node when "function()" arrived', function() {
const typeExprStr = 'function()';
const node = Parser.parse(typeExprStr);
it('should return a tuple type node when "[TupleAnyVarargs, ...]" arrived', function() {
const typeExprStr = '[TupleAnyVarargs, ...]';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[], null,
{ 'this': null, 'new': null }
);
const expectedNode = createTupleTypeNode([
createTypeNameNode('TupleAnyVarargs'),
createVariadicTypeNode(
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with a param when "function(Param)" arrived', function() {
const typeExprStr = 'function(Param)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[ createTypeNameNode('Param') ], null,
{ 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with several params when "function(Param1,Param2)"' +
' arrived', function() {
const typeExprStr = 'function(Param1,Param2)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[ createTypeNameNode('Param1'), createTypeNameNode('Param2') ], null,
{ 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with variadic params when "function(...VariadicParam)"' +
' arrived', function() {
const typeExprStr = 'function(...VariadicParam)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[
createVariadicTypeNode(
createTypeNameNode('VariadicParam'),
VariadicTypeSyntax.PREFIX_DOTS
),
],
null, { 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with variadic params when "function(Param,...VariadicParam)"' +
' arrived', function() {
const typeExprStr = 'function(Param,...VariadicParam)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[
createTypeNameNode('Param'),
createVariadicTypeNode(
createTypeNameNode('VariadicParam'),
VariadicTypeSyntax.PREFIX_DOTS
),
],
null, { 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw an error when "function(...VariadicParam, UnexpectedLastParam)"' +
' arrived', function() {
const typeExprStr = 'function(...VariadicParam, UnexpectedLastParam)';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
it('should return a function type node with returns when "function():Returned"' +
' arrived', function() {
const typeExprStr = 'function():Returned';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[], createTypeNameNode('Returned'),
{ 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with a context type when "function(this:ThisObject)"' +
' arrived', function() {
const typeExprStr = 'function(this:ThisObject)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[], null,
{ 'this': createTypeNameNode('ThisObject'), 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with a context type when ' +
'"function(this:ThisObject, param1)" arrived', function() {
const typeExprStr = 'function(this:ThisObject, param1)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[createTypeNameNode('param1')],
null,
VariadicTypeSyntax.ONLY_DOTS
),
]);
{ 'this': createTypeNameNode('ThisObject'), 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "[][]" arrived', function() {
const typeExprStr = '[][]';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'),
[
createTupleTypeNode([]),
],
GenericTypeSyntax.SQUARE_BRACKET);
it('should return a function type node as a constructor when "function(new:NewObject)"' +
' arrived', function() {
const typeExprStr = 'function(new:NewObject)';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[], null,
{ 'this': null, 'new': createTypeNameNode('NewObject') }
);
it('should return a generic type node when "[TupleType][]" arrived', function() {
const typeExprStr = '[TupleType][]';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'),
[
createTupleTypeNode([
createTypeNameNode('TupleType'),
]),
],
GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node as a constructor when ' +
'"function(new:NewObject, param1)" arrived', function() {
const typeExprStr = 'function(new:NewObject, param1)';
const node = Parser.parse(typeExprStr);
it('should return a generic type node when "[TupleType1, TupleType2][]" arrived', function() {
const typeExprStr = '[TupleType1, TupleType2][]';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[createTypeNameNode('param1')],
null,
{ 'this': null, 'new': createTypeNameNode('NewObject') }
);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'),
[
createTupleTypeNode([
createTypeNameNode('TupleType1'),
createTypeNameNode('TupleType2'),
]),
],
GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should throw an error when "function(new:NewObject, this:ThisObject)" ' +
'arrived', function() {
const typeExprStr = 'function(new:NewObject, this:ThisObject)';
it('should return a generic type node when "Generic<ParamType>" arrived', function() {
const typeExprStr = 'Generic<ParamType>';
const node = Parser.parse(typeExprStr);
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.ANGLE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should throw an error when "function(this:ThisObject, new:NewObject)" ' +
'arrived', function() {
const typeExprStr = 'function(this:ThisObject, new:NewObject)';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
it('should return a generic type node when "Generic<Inner<ParamType>>" arrived', function() {
const typeExprStr = 'Generic<Inner<ParamType>>';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createGenericTypeNode(
createTypeNameNode('Inner'), [ createTypeNameNode('ParamType') ]
),
], GenericTypeSyntax.ANGLE_BRACKET);
it('should return a function type node when "function( Param1 , Param2 ) : Returned"' +
' arrived', function() {
const typeExprStr = 'function( Param1 , Param2 ) : Returned';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[ createTypeNameNode('Param1'), createTypeNameNode('Param2') ],
createTypeNameNode('Returned'),
{ 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "Generic<ParamType1,ParamType2>"' +
' arrived', function() {
const typeExprStr = 'Generic<ParamType1,ParamType2>';
const node = Parser.parse(typeExprStr);
it('should return an arrow function type node when "() => string" arrived', function() {
const typeExprStr = '() => string';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET);
const expectedNode = createArrowFunctionTypeNode(
[], createTypeNameNode('string'),
{ 'new': null }
);
expect(node).to.deep.equal(expectedNode);
expect(node).to.deep.equal(expectedNode);
});
});
describe('BroadNamepathExpr types', function () {
describe('Single component', function () {
it('should return a type name node when "TypeName" arrived', function() {
const typeExprStr = 'TypeName';
const node = Parser.parse(typeExprStr);
it('should return a generic type node when "Generic < ParamType1 , ParamType2 >"' +
' arrived', function() {
const typeExprStr = 'Generic < ParamType1, ParamType2 >';
const node = Parser.parse(typeExprStr);
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
it('should return a type name node when "my-type" arrived', function() {
const typeExprStr = 'my-type';
const node = Parser.parse(typeExprStr);
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "Generic.<ParamType>" arrived', function() {
const typeExprStr = 'Generic.<ParamType>';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.ANGLE_BRACKET_WITH_DOT);
it('should return a type name node when "$" arrived', function() {
const typeExprStr = '$';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "Generic.<ParamType1,ParamType2>"' +
' arrived', function() {
const typeExprStr = 'Generic.<ParamType1,ParamType2>';
const node = Parser.parse(typeExprStr);
it('should return a type name node when "_" arrived', function() {
const typeExprStr = '_';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET_WITH_DOT);
const expectedNode = createTypeNameNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
});
describe('Multipart', function () {
it('should return a member type node when "owner.Member" arrived', function() {
const typeExprStr = 'owner.Member';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Member'
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "Generic .< ParamType1 , ParamType2 >"' +
' arrived', function() {
const typeExprStr = 'Generic .< ParamType1 , ParamType2 >';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Generic'), [
createTypeNameNode('ParamType1'),
createTypeNameNode('ParamType2'),
], GenericTypeSyntax.ANGLE_BRACKET_WITH_DOT);
it('should return a member type node when "owner . Member" arrived', function() {
const typeExprStr = 'owner . Member';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Member');
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "ParamType[]" arrived', function() {
const typeExprStr = 'ParamType[]';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.SQUARE_BRACKET);
it('should return a member type node when \'owner."Mem.ber"\' arrived', function() {
const typeExprStr = 'owner."Mem.ber"';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Mem.ber',
'double'
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a generic type node when "ParamType[][]" arrived', function() {
const typeExprStr = 'ParamType[][]';
const node = Parser.parse(typeExprStr);
it('should return a member type node when \'owner."Mem\\ber"\' arrived', function() {
const typeExprStr = 'owner."Mem\\ber"';
const node = Parser.parse(typeExprStr);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'), [
createGenericTypeNode(
createTypeNameNode('Array'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.SQUARE_BRACKET),
], GenericTypeSyntax.SQUARE_BRACKET);
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Mem\\ber',
'double'
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a member type node when "owner.\'Mem\\ber\'" arrived', function() {
const typeExprStr = 'owner.\'Mem\\ber\'';
const node = Parser.parse(typeExprStr);
it('should return a generic type node when "ParamType [ ] [ ]" arrived', function() {
const typeExprStr = 'ParamType [ ] [ ]';
const node = Parser.parse(typeExprStr);
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Mem\\ber',
'single'
);
const expectedNode = createGenericTypeNode(
createTypeNameNode('Array'), [
createGenericTypeNode(
createTypeNameNode('Array'), [
createTypeNameNode('ParamType'),
], GenericTypeSyntax.SQUARE_BRACKET),
], GenericTypeSyntax.SQUARE_BRACKET);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a member type node when \'owner."Mem.ber\\""\' arrived', function() {
const typeExprStr = 'owner."Mem.ber\\""';
const node = Parser.parse(typeExprStr);
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Mem.ber"',
'double'
);
it('should return an optional type node when "string=" arrived', function() {
const typeExprStr = 'string=';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return a member type node when \'owner."Me\\m\\\\ber"\' arrived', function() {
const typeExprStr = 'owner."Me\\m\\"ber\\\\"';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Me\\m"ber\\',
'double');
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "=string" arrived (deprecated)', function() {
const typeExprStr = '=string';
const node = Parser.parse(typeExprStr);
it('should return a member type node when \'owner."Mem\\\\ber\\""\' arrived', function() {
const typeExprStr = 'owner."Mem\\\\ber\\""';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.PREFIX_EQUALS_SIGN
);
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Mem\\ber"',
'double');
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should throw when \'owner."Mem.ber\\"\' arrived', function() {
const typeExprStr = 'owner."Mem.ber\\"';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('Expected "\\""');
});
it('should return a nullable type node when "?string" arrived', function() {
const typeExprStr = '?string';
const node = Parser.parse(typeExprStr);
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.PREFIX_QUESTION_MARK
);
it('should return a member type node when "superOwner.owner.Member" arrived', function() {
const typeExprStr = 'superOwner.owner.Member';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createMemberTypeNode(
createMemberTypeNode(
createTypeNameNode('superOwner'), 'owner'),
'Member');
expect(node).to.deep.equal(expectedNode);
});
it('should return a nullable type node when "string?" arrived (deprecated)', function() {
const typeExprStr = 'string?';
const node = Parser.parse(typeExprStr);
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.SUFFIX_QUESTION_MARK
);
it('should return a member type node when "superOwner.owner.Member=" arrived', function() {
const typeExprStr = 'superOwner.owner.Member=';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createOptionalTypeNode(
createMemberTypeNode(
createMemberTypeNode(
createTypeNameNode('superOwner'),
'owner'),
'Member'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "string =" arrived', function() {
const typeExprStr = 'string =';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return an inner member type node when "owner~innerMember" arrived', function() {
const typeExprStr = 'owner~innerMember';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createInnerMemberTypeNode(
createTypeNameNode('owner'),
'innerMember');
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "= string" arrived (deprecated)', function() {
const typeExprStr = '= string';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.PREFIX_EQUALS_SIGN
);
it('should return an inner member type node when "owner ~ innerMember" arrived', function() {
const typeExprStr = 'owner ~ innerMember';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createInnerMemberTypeNode(
createTypeNameNode('owner'),
'innerMember');
expect(node).to.deep.equal(expectedNode);
});
it('should return a nullable type node when "? string" arrived', function() {
const typeExprStr = '? string';
const node = Parser.parse(typeExprStr);
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.PREFIX_QUESTION_MARK
);
it('should return an inner member type node when "superOwner~owner~innerMember" ' +
'arrived', function() {
const typeExprStr = 'superOwner~owner~innerMember';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createInnerMemberTypeNode(
createInnerMemberTypeNode(
createTypeNameNode('superOwner'), 'owner'),
'innerMember');
expect(node).to.deep.equal(expectedNode);
});
it('should return a nullable type node when "string ?" arrived (deprecated)', function() {
const typeExprStr = 'string ?';
const node = Parser.parse(typeExprStr);
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.SUFFIX_QUESTION_MARK
);
it('should return an inner member type node when "superOwner~owner~innerMember=" ' +
'arrived', function() {
const typeExprStr = 'superOwner~owner~innerMember=';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createOptionalTypeNode(
createInnerMemberTypeNode(
createInnerMemberTypeNode(
createTypeNameNode('superOwner'),
'owner'),
'innerMember'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "?string=" arrived', function() {
const typeExprStr = '?string=';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.PREFIX_QUESTION_MARK
),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return an instance member type node when "owner#instanceMember" arrived', function() {
const typeExprStr = 'owner#instanceMember';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createInstanceMemberTypeNode(
createTypeNameNode('owner'),
'instanceMember');
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "string?=" arrived', function() {
const typeExprStr = 'string?=';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.SUFFIX_QUESTION_MARK
),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return an instance member type node when "owner # instanceMember" ' +
'arrived', function() {
const typeExprStr = 'owner # instanceMember';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createInstanceMemberTypeNode(
createTypeNameNode('owner'),
'instanceMember');
expect(node).to.deep.equal(expectedNode);
});
it('should throw an error when "?!string" arrived', function() {
const typeExprStr = '?!string';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
});
it('should return an instance member type node when "superOwner#owner#instanceMember" ' +
'arrived', function() {
const typeExprStr = 'superOwner#owner#instanceMember';
const node = Parser.parse(typeExprStr);
const expectedNode = createInstanceMemberTypeNode(
createInstanceMemberTypeNode(
createTypeNameNode('superOwner'), 'owner'),
'instanceMember');
it('should throw an error when "!?string" arrived', function() {
const typeExprStr = '!?string';
expect(node).to.deep.equal(expectedNode);
});
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
});
it('should return an instance member type node when "superOwner#owner#instanceMember=" ' +
'arrived', function() {
const typeExprStr = 'superOwner#owner#instanceMember=';
const node = Parser.parse(typeExprStr);
it('should return a variadic type node when "...PrefixVariadic" arrived', function() {
const typeExprStr = '...PrefixVariadic';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createInstanceMemberTypeNode(
createInstanceMemberTypeNode(
createTypeNameNode('superOwner'),
'owner'),
'instanceMember'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
const expectedNode = createVariadicTypeNode(
createTypeNameNode('PrefixVariadic'),
VariadicTypeSyntax.PREFIX_DOTS
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a member type node when "owner.event:Member" arrived', function() {
const typeExprStr = 'owner.event:Member';
const node = Parser.parse(typeExprStr);
it('should return a variadic type node when "SuffixVariadic..." arrived', function() {
const typeExprStr = 'SuffixVariadic...';
const node = Parser.parse(typeExprStr);
const expectedNode = createMemberTypeNode(
createTypeNameNode('owner'),
'Member',
'none',
true);
const expectedNode = createVariadicTypeNode(
createTypeNameNode('SuffixVariadic'),
VariadicTypeSyntax.SUFFIX_DOTS
);
expect(node).to.deep.equal(expectedNode);
});
});
describe('external', function () {
it('should return an external name node when "external:string" arrived', function() {
const typeExprStr = 'external:string';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createExternalNameNode('string');
expect(node).to.deep.equal(expectedNode);
});
it('should return a variadic type node when "..." arrived', function() {
const typeExprStr = '...';
const node = Parser.parse(typeExprStr);
it('should return an external name node when "external : String#rot13" arrived', function() {
const typeExprStr = 'external : String#rot13';
const node = Parser.parse(typeExprStr);
const expectedNode = createVariadicTypeNode(
null,
VariadicTypeSyntax.ONLY_DOTS
);
const expectedNode = createInstanceMemberTypeNode(
createExternalNameNode('String'),
'rot13'
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return an external name node when `external:"jQuery.fn"` arrived', function() {
const typeExprStr = 'external:"jQuery.fn"';
const node = Parser.parse(typeExprStr);
const expectedNode = createExternalNameNode('jQuery.fn', 'double');
expect(node).to.deep.equal(expectedNode);
});
it('should return a variadic type node when "...!Object" arrived', function() {
const typeExprStr = '...!Object';
const node = Parser.parse(typeExprStr);
it('should return an external name node when `external:"jQuery.fn".someMethod#event:abc` arrived', function() {
const typeExprStr = 'external:"jQuery.fn".someMethod#event:abc';
const node = Parser.parse(typeExprStr);
const expectedNode = createVariadicTypeNode(
createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.PREFIX_BANG
),
VariadicTypeSyntax.PREFIX_DOTS
);
const expectedNode = createInstanceMemberTypeNode(
createMemberTypeNode(
createExternalNameNode('jQuery.fn', 'double'),
'someMethod'
),
'abc',
'none',
true
);
expect(node).to.deep.equal(expectedNode);
});
});
expect(node).to.deep.equal(expectedNode);
});
describe('module', function () {
it('should return a module name node when "module:path/to/file" arrived', function() {
const typeExprStr = 'module:path/to/file';
const node = Parser.parse(typeExprStr);
const expectedNode = createModuleNameNode(createFilePathNode('path/to/file'));
expect(node).to.deep.equal(expectedNode);
});
it('should return a variadic type node when "...?" arrived', function() {
const typeExprStr = '...?';
const node = Parser.parse(typeExprStr);
const expectedNode = createVariadicTypeNode(
createUnknownTypeNode(),
VariadicTypeSyntax.PREFIX_DOTS
);
it('should return a module name node when "module : path/to/file" arrived', function() {
const typeExprStr = 'module : path/to/file';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(createFilePathNode('path/to/file'));
expect(node).to.deep.equal(expectedNode);
});
it('should return a not nullable type node when "!Object" arrived', function() {
const typeExprStr = '!Object';
const node = Parser.parse(typeExprStr);
it('should return a member node when "(module:path/to/file).member" arrived', function() {
const typeExprStr = '(module:path/to/file).member';
const node = Parser.parse(typeExprStr);
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.PREFIX_BANG
);
const expectedNode = createMemberTypeNode(
createParenthesizedNode(
createModuleNameNode(createFilePathNode('path/to/file'))
),
'member'
);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a member node when "module:path/to/file.member" arrived', function() {
const typeExprStr = 'module:path/to/file.member';
const node = Parser.parse(typeExprStr);
it('should return a not nullable type node when "Object!" arrived', function() {
const typeExprStr = 'Object!';
const node = Parser.parse(typeExprStr);
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path/to/file'), 'member')
);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.SUFFIX_BANG
);
it('should return a member node when "module:path/to/file.event:member" arrived', function() {
const typeExprStr = 'module:path/to/file.event:member';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path/to/file'), 'member', 'none', true)
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a member node when \'module:"path/to/file".event:member\' arrived', function() {
const typeExprStr = 'module:"path/to/file".event:member';
const node = Parser.parse(typeExprStr);
it('should return a not nullable type node when "! Object" arrived', function() {
const typeExprStr = '! Object';
const node = Parser.parse(typeExprStr);
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path/to/file', 'double'), 'member', 'none', true)
);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.PREFIX_BANG
);
it('should return a member node when \'module:"path\\\\to\\file\\"".event:member\' arrived', function() {
const typeExprStr = 'module:"path\\\\to\\file\\"".event:member';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path\\to\\file"', 'double'), 'member', 'none', true)
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw when \'module:"path/t"o/file".event:member\' arrived', function() {
const typeExprStr = 'module:"path/t"o/file".event:member';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('Expected "!", "#", ".", "...", ".<", "/", "<", "=", "?", "[", "|", "~", [ \\t\\r\\n ], or end of input but "o" found.');
});
it('should return a not nullable type node when "Object !" arrived', function() {
const typeExprStr = 'Object !';
const node = Parser.parse(typeExprStr);
it('should throw when \'module:"path/t\\\\"o/file".event:member', function() {
const typeExprStr = 'module:"path/t\\\\"o/file".event:member';
expect(function () {
Parser.parse(typeExprStr);
}).to.throw('Expected "!", "#", ".", "...", ".<", "/", "<", "=", "?", "[", "|", "~", [ \\t\\r\\n ], or end of input but "o" found.');
});
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.SUFFIX_BANG
);
it('should return a member node when "module:\'path/to/file\'.event:member" arrived', function() {
const typeExprStr = "module:'path/to/file'.event:member";
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
const expectedNode = createModuleNameNode(
createMemberTypeNode(createFilePathNode('path/to/file', 'single'), 'member', 'none', true)
);
expect(node).to.deep.equal(expectedNode);
});
});
});
describe('Types with modifiers', function () {
it('should return an optional unknown type node when "?=" arrived', function() {
const typeExprStr = '?=';
const node = Parser.parse(typeExprStr);
it('should return a function type node when "function()" arrived', function() {
const typeExprStr = 'function()';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createUnknownTypeNode(),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[], null,
{ 'this': null, 'new': null }
);
it('should return an optional type node when "string=" arrived', function() {
const typeExprStr = 'string=';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with a param when "function(Param)" arrived', function() {
const typeExprStr = 'function(Param)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[ createTypeNameNode('Param') ], null,
{ 'this': null, 'new': null }
);
it('should return an optional type node when "=string" arrived (deprecated)', function() {
const typeExprStr = '=string';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.PREFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with several params when "function(Param1,Param2)"' +
' arrived', function() {
const typeExprStr = 'function(Param1,Param2)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[ createTypeNameNode('Param1'), createTypeNameNode('Param2') ], null,
{ 'this': null, 'new': null }
);
it('should return a nullable type node when "?string" arrived', function() {
const typeExprStr = '?string';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.PREFIX_QUESTION_MARK
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with variadic params when "function(...VariadicParam)"' +
' arrived', function() {
const typeExprStr = 'function(...VariadicParam)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[
createVariadicTypeNode(
createTypeNameNode('VariadicParam'),
VariadicTypeSyntax.PREFIX_DOTS
),
],
null, { 'this': null, 'new': null }
);
it('should return a nullable type node when "string?" arrived (deprecated)', function() {
const typeExprStr = 'string?';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.SUFFIX_QUESTION_MARK
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node with variadic params when "function(Param,...VariadicParam)"' +
' arrived', function() {
const typeExprStr = 'function(Param,...VariadicParam)';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[
createTypeNameNode('Param'),
createVariadicTypeNode(
createTypeNameNode('VariadicParam'),
VariadicTypeSyntax.PREFIX_DOTS
),
],
null, { 'this': null, 'new': null }
);
it('should return an optional type node when "string =" arrived', function() {
const typeExprStr = 'string =';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw an error when "function(...VariadicParam, UnexpectedLastParam)"' +
' arrived', function() {
const typeExprStr = 'function(...VariadicParam, UnexpectedLastParam)';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
});
it('should return an optional type node when "= string" arrived (deprecated)', function() {
const typeExprStr = '= string';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createTypeNameNode('string'),
OptionalTypeSyntax.PREFIX_EQUALS_SIGN
);
it('should return a function type node with returns when "function():Returned"' +
' arrived', function() {
const typeExprStr = 'function():Returned';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[], createTypeNameNode('Returned'),
{ 'this': null, 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a nullable type node when "? string" arrived', function() {
const typeExprStr = '? string';
const node = Parser.parse(typeExprStr);
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.PREFIX_QUESTION_MARK
);
it('should return a function type node with a context type when "function(this:ThisObject)"' +
' arrived', function() {
const typeExprStr = 'function(this:ThisObject)';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[], null,
{ 'this': createTypeNameNode('ThisObject'), 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a nullable type node when "string ?" arrived (deprecated)', function() {
const typeExprStr = 'string ?';
const node = Parser.parse(typeExprStr);
const expectedNode = createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.SUFFIX_QUESTION_MARK
);
it('should return a function type node with a context type when ' +
'"function(this:ThisObject, param1)" arrived', function() {
const typeExprStr = 'function(this:ThisObject, param1)';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[createTypeNameNode('param1')],
null,
{ 'this': createTypeNameNode('ThisObject'), 'new': null }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "?string=" arrived', function() {
const typeExprStr = '?string=';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.PREFIX_QUESTION_MARK
),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return a function type node as a constructor when "function(new:NewObject)"' +
' arrived', function() {
const typeExprStr = 'function(new:NewObject)';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[], null,
{ 'this': null, 'new': createTypeNameNode('NewObject') }
);
expect(node).to.deep.equal(expectedNode);
});
it('should return an optional type node when "string?=" arrived', function() {
const typeExprStr = 'string?=';
const node = Parser.parse(typeExprStr);
const expectedNode = createOptionalTypeNode(
createNullableTypeNode(
createTypeNameNode('string'),
NullableTypeSyntax.SUFFIX_QUESTION_MARK
),
OptionalTypeSyntax.SUFFIX_EQUALS_SIGN
);
it('should return a function type node as a constructor when ' +
'"function(new:NewObject, param1)" arrived', function() {
const typeExprStr = 'function(new:NewObject, param1)';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createFunctionTypeNode(
[createTypeNameNode('param1')],
null,
{ 'this': null, 'new': createTypeNameNode('NewObject') }
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw an error when "?!string" arrived', function() {
const typeExprStr = '?!string';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
it('should throw an error when "function(new:NewObject, this:ThisObject)" ' +
'arrived', function() {
const typeExprStr = 'function(new:NewObject, this:ThisObject)';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
});
it('should throw an error when "!?string" arrived', function() {
const typeExprStr = '!?string';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
it('should throw an error when "function(this:ThisObject, new:NewObject)" ' +
'arrived', function() {
const typeExprStr = 'function(this:ThisObject, new:NewObject)';
it('should return a variadic type node when "...PrefixVariadic" arrived', function() {
const typeExprStr = '...PrefixVariadic';
const node = Parser.parse(typeExprStr);
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
});
const expectedNode = createVariadicTypeNode(
createTypeNameNode('PrefixVariadic'),
VariadicTypeSyntax.PREFIX_DOTS
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a function type node when "function( Param1 , Param2 ) : Returned"' +
' arrived', function() {
const typeExprStr = 'function( Param1 , Param2 ) : Returned';
const node = Parser.parse(typeExprStr);
const expectedNode = createFunctionTypeNode(
[ createTypeNameNode('Param1'), createTypeNameNode('Param2') ],
createTypeNameNode('Returned'),
{ 'this': null, 'new': null }
);
it('should return a variadic type node when "SuffixVariadic..." arrived', function() {
const typeExprStr = 'SuffixVariadic...';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createVariadicTypeNode(
createTypeNameNode('SuffixVariadic'),
VariadicTypeSyntax.SUFFIX_DOTS
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0123456789" arrived', function() {
const typeExprStr = '0123456789';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a variadic type node when "..." arrived', function() {
const typeExprStr = '...';
const node = Parser.parse(typeExprStr);
const expectedNode = createVariadicTypeNode(
null,
VariadicTypeSyntax.ONLY_DOTS
);
it('should return a number value type node when "0.0" arrived', function() {
const typeExprStr = '0.0';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a variadic type node when "...!Object" arrived', function() {
const typeExprStr = '...!Object';
const node = Parser.parse(typeExprStr);
it('should return a number value type node when "-0" arrived', function() {
const typeExprStr = '-0';
const node = Parser.parse(typeExprStr);
const expectedNode = createVariadicTypeNode(
createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.PREFIX_BANG
),
VariadicTypeSyntax.PREFIX_DOTS
);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0b01" arrived', function() {
const typeExprStr = '0b01';
const node = Parser.parse(typeExprStr);
it('should return a variadic type node when "...?" arrived', function() {
const typeExprStr = '...?';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createVariadicTypeNode(
createUnknownTypeNode(),
VariadicTypeSyntax.PREFIX_DOTS
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0o01234567" arrived', function() {
const typeExprStr = '0o01234567';
const node = Parser.parse(typeExprStr);
it('should return a not nullable type node when "!Object" arrived', function() {
const typeExprStr = '!Object';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.PREFIX_BANG
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a number value type node when "0x0123456789abcdef" arrived', function() {
const typeExprStr = '0x0123456789abcdef';
const node = Parser.parse(typeExprStr);
const expectedNode = createNumberValueNode(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
it('should return a not nullable type node when "Object!" arrived', function() {
const typeExprStr = 'Object!';
const node = Parser.parse(typeExprStr);
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.SUFFIX_BANG
);
it('should return a string value type node when \'""\' arrived', function() {
const typeExprStr = '""';
const node = Parser.parse(typeExprStr);
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createStringValueNode('');
expect(node).to.deep.equal(expectedNode);
});
it('should return a not nullable type node when "! Object" arrived', function() {
const typeExprStr = '! Object';
const node = Parser.parse(typeExprStr);
it('should return a string value type node when \'"string"\' arrived', function() {
const typeExprStr = '"string"';
const node = Parser.parse(typeExprStr);
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.PREFIX_BANG
);
const expectedNode = createStringValueNode('string');
expect(node).to.deep.equal(expectedNode);
});
expect(node).to.deep.equal(expectedNode);
});
it('should return a string value type node when \'"マルチバイト"\' arrived', function() {
const typeExprStr = '"マルチバイト"';
const node = Parser.parse(typeExprStr);
it('should return a not nullable type node when "Object !" arrived', function() {
const typeExprStr = 'Object !';
const node = Parser.parse(typeExprStr);
const expectedNode = createStringValueNode('マルチバイト');
expect(node).to.deep.equal(expectedNode);
const expectedNode = createNotNullableTypeNode(
createTypeNameNode('Object'),
NotNullableTypeSyntax.SUFFIX_BANG
);
expect(node).to.deep.equal(expectedNode);
});
});
describe('Type combinations', function () {
it('should return a string value type node when \'"\\n\\"\\t"\' arrived', function() {
const typeExprStr = '"\\n\\"\\t"';
const node = Parser.parse(typeExprStr);
it('should return a union type when "LeftType|RightType" arrived', function() {
const typeExprStr = 'LeftType|RightType';
const node = Parser.parse(typeExprStr);
const expectedNode = createStringValueNode('\\n"\\t');
expect(node).to.deep.equal(expectedNode);
});
const expectedNode = createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType'),
UnionTypeSyntax.PIPE
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw a syntax error when "" arrived', function() {
const typeExprStr = '';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
});
it('should return a union type when "LeftType|MiddleType|RightType" arrived', function() {
const typeExprStr = 'LeftType|MiddleType|RightType';
const node = Parser.parse(typeExprStr);
const expectedNode = createUnionTypeNode(
createTypeNameNode('LeftType'),
createUnionTypeNode(
createTypeNameNode('MiddleType'),
createTypeNameNode('RightType'),
UnionTypeSyntax.PIPE
), UnionTypeSyntax.PIPE);
it('should throw a syntax error when "Invalid type" arrived', function() {
const typeExprStr = 'Invalid type';
expect(node).to.deep.equal(expectedNode);
});
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
it('should return a union type when "(LeftType|RightType)" arrived', function() {
const typeExprStr = '(LeftType|RightType)';
const node = Parser.parse(typeExprStr);
const expectedNode = createParenthesizedNode(
createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType')
)
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a union type when "( LeftType | RightType )" arrived', function() {
const typeExprStr = '( LeftType | RightType )';
const node = Parser.parse(typeExprStr);
const expectedNode = createParenthesizedNode(
createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType')
)
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a union type when "LeftType/RightType" arrived', function() {
const typeExprStr = 'LeftType/RightType';
const node = Parser.parse(typeExprStr);
const expectedNode = createUnionTypeNode(
createTypeNameNode('LeftType'),
createTypeNameNode('RightType'),
UnionTypeSyntax.SLASH
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw a syntax error when "(unclosedParenthesis, " arrived', function() {
const typeExprStr = '(unclosedParenthesis, ';
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.JSDocTypeSyntaxError);
});
});
it('should throw a syntax error when "Promise*Error" arrived', function() {
const typeExprStr = 'Promise*Error';
it('should return a type query type node when "typeof foo" arrived', function() {
const typeExprStr = 'typeof foo';
const node = Parser.parse(typeExprStr);
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
const expectedNode = createTypeQueryNode(
createTypeNameNode('foo')
);
expect(node).to.deep.equal(expectedNode);
});
it('should throw a syntax error when "(unclosedParenthesis, " arrived', function() {
const typeExprStr = '(unclosedParenthesis, ';
it('should return a key query type node when "keyof foo" arrived', function() {
const typeExprStr = 'keyof foo';
const node = Parser.parse(typeExprStr);
expect(function() {
Parser.parse(typeExprStr);
}).to.throw(Parser.SyntaxError);
const expectedNode = createKeyQueryNode(
createTypeNameNode('foo')
);
expect(node).to.deep.equal(expectedNode);
});
it('should return a key query type node when "keyof typeof foo" arrived', function() {
const typeExprStr = 'keyof typeof foo';
const node = Parser.parse(typeExprStr);
const expectedNode = createKeyQueryNode(
createTypeQueryNode(
createTypeNameNode('foo')
)
);
expect(node).to.deep.equal(expectedNode);
});
describe('operator precedence', function() {

@@ -1393,2 +1732,5 @@ context('when "Foo|function():Returned?" arrived', function() {

/**
* @param {string} typeName
*/
function createTypeNameNode(typeName) {

@@ -1420,6 +1762,7 @@ return {

function createExternalNameNode(value) {
function createExternalNameNode(name, quoteStyle = 'none') {
return {
type: NodeType.EXTERNAL,
value: value,
name,
quoteStyle,
};

@@ -1452,3 +1795,3 @@ }

function createMemberTypeNode(ownerTypeExpr, memberTypeName, hasEventPrefix) {
function createMemberTypeNode(ownerTypeExpr, memberTypeName, quoteStyle = 'none', hasEventPrefix = false) {
return {

@@ -1458,7 +1801,8 @@ type: NodeType.MEMBER,

name: memberTypeName,
hasEventPrefix: hasEventPrefix || false,
quoteStyle,
hasEventPrefix,
};
}
function createInnerMemberTypeNode(ownerTypeExpr, memberTypeName, hasEventPrefix) {
function createInnerMemberTypeNode(ownerTypeExpr, memberTypeName, quoteStyle = 'none', hasEventPrefix = false) {
return {

@@ -1468,7 +1812,8 @@ type: NodeType.INNER_MEMBER,

name: memberTypeName,
hasEventPrefix: hasEventPrefix || false,
quoteStyle,
hasEventPrefix,
};
}
function createInstanceMemberTypeNode(ownerTypeExpr, memberTypeName, hasEventPrefix) {
function createInstanceMemberTypeNode(ownerTypeExpr, memberTypeName, quoteStyle = 'none', hasEventPrefix = false) {
return {

@@ -1478,3 +1823,4 @@ type: NodeType.INSTANCE_MEMBER,

name: memberTypeName,
hasEventPrefix: hasEventPrefix || false,
quoteStyle,
hasEventPrefix,
};

@@ -1507,3 +1853,3 @@ }

function createRecordEntryNode(key, valueTypeExpr) {
function createRecordEntryNode(key, valueTypeExpr, quoteStyle = 'none') {
return {

@@ -1513,2 +1859,3 @@ type: NodeType.RECORD_ENTRY,

value: valueTypeExpr,
quoteStyle,
};

@@ -1518,3 +1865,3 @@ }

/**
* @template T
* @template {Node} T
* @param {T[]} tupleEntries

@@ -1538,2 +1885,11 @@ */

function createArrowFunctionTypeNode(paramNodes, returnedNode, modifierMap) {
return {
type: NodeType.ARROW,
params: paramNodes,
returns: returnedNode,
new: modifierMap.new,
};
}
function createFunctionTypeNode(paramNodes, returnedNode, modifierMap) {

@@ -1556,5 +1912,6 @@ return {

function createStringValueNode(stringLiteral) {
function createStringValueNode(stringLiteral, quoteStyle = 'double') {
return {
type: NodeType.STRING_VALUE,
quoteStyle,
string: stringLiteral,

@@ -1564,6 +1921,7 @@ };

function createFilePathNode(filePath) {
function createFilePathNode(filePath, quoteStyle = 'none') {
return {
type: NodeType.FILE_PATH,
path: filePath,
quoteStyle,
};

@@ -1578,1 +1936,23 @@ }

}
/**
* @template {Node} T
* @param {T} name
*/
function createTypeQueryNode(name) {
return {
type: NodeType.TYPE_QUERY,
name: name,
}
}
/**
* @template {Node} T
* @param {T} value
*/
function createKeyQueryNode(value) {
return {
type: NodeType.KEY_QUERY,
value: value,
};
}

@@ -12,349 +12,474 @@ 'use strict';

describe('publish', function() {
it('should have a default publisher for each node type', function() {
const publisher = createDefaultPublisher();
expect(Object.getOwnPropertyNames(publisher)).to.include.members(
Object.getOwnPropertyNames(NodeType).map(p => NodeType[p])
);
});
describe('Publishers', function () {
it('should have a default publisher for each node type', function() {
const publisher = createDefaultPublisher();
expect(Object.getOwnPropertyNames(publisher)).to.include.members(
Object.getOwnPropertyNames(NodeType).map(p => NodeType[p])
);
});
it('should can take a custom publisher by the 2nd argument', function() {
const ast = {
type: 'NAME',
name: 'MyClass',
};
it('should return a primitive type name', function() {
const node = parse('boolean');
expect(publish(node)).to.equal('boolean');
const customPublisher = createDefaultPublisher();
customPublisher.NAME = function(node) {
return '<a href="./types/' + node.name + '.html">' + node.name + '</a>';
};
const string = publish(ast, customPublisher);
expect(string).to.equal('<a href="./types/MyClass.html">MyClass</a>');
});
});
describe('Primitive types', function () {
it('should return an undefined type with an "undefined" keyword', function() {
const node = parse('undefined');
expect(publish(node)).to.equal('undefined');
});
it('should return a global type name', function() {
const node = parse('Window');
expect(publish(node)).to.equal('Window');
});
it('should return a null type with an "null" keyword', function() {
const node = parse('null');
expect(publish(node)).to.equal('null');
});
it('should return a primitive (boolean) type name', function() {
const node = parse('boolean');
expect(publish(node)).to.equal('boolean');
});
it('should return an user-defined type name', function() {
const node = parse('goog.ui.Menu');
expect(publish(node)).to.equal('goog.ui.Menu');
});
it('should return a string value type', function() {
const node = parse('"stringValue"');
expect(publish(node)).to.equal('"stringValue"');
});
it('should return a string value type (single quotes)', function() {
const node = parse("'stringValue'");
expect(publish(node)).to.equal("'stringValue'");
});
it('should return a generic type has a parameter', function() {
const node = parse('Array.<string>');
expect(publish(node)).to.equal('Array.<string>');
});
it('should return a string value type with escaped quote', function() {
const node = parse('"string \\"Value"');
expect(publish(node)).to.equal('"string \\"Value"');
});
it('should return a string value type with single extra backslash for odd count backslash series not before a quote', function() {
const node = parse('"\\Odd count backslash sequence not before a quote\\add\\\\\\one backslash\\."');
expect(publish(node)).to.equal('"\\\\Odd count backslash sequence not before a quote\\\\add\\\\\\\\one backslash\\\\."');
});
it('should return a generic type has 2 parameters', function() {
const node = parse('Object.<string, number>');
expect(publish(node)).to.equal('Object.<string, number>');
});
it('should return a string value type without adding backslashes for escaped backslash sequences (i.e., even count)', function() {
const node = parse('"\\\\Even count (escaped)\\\\\\\\backslash sequences\\\\remain\\\\"');
expect(publish(node)).to.equal('"\\\\Even count (escaped)\\\\\\\\backslash sequences\\\\remain\\\\"');
});
it('should return a JsDoc-formal generic type', function() {
const node = parse('String[]');
expect(publish(node)).to.equal('String[]');
});
it('should return a number value type', function() {
const node = parse('0123456789');
expect(publish(node)).to.equal('0123456789');
});
it('should return a formal type union', function() {
const node = parse('(number|boolean)');
expect(publish(node)).to.equal('(number|boolean)');
});
it('should return a bin number value type', function() {
const node = parse('0b01');
expect(publish(node)).to.equal('0b01');
});
it('should return a informal type union', function() {
const node = parse('number|boolean');
expect(publish(node)).to.equal('number|boolean');
});
it('should return an oct number value type', function() {
const node = parse('0o01234567');
expect(publish(node)).to.equal('0o01234567');
});
it('should return a type query node', function() {
const node = parse('typeof x');
expect(publish(node)).to.equal('typeof x');
});
it('should return an import type node', function() {
const node = parse('import("./lodash4ever")');
expect(publish(node)).to.equal('import("./lodash4ever")');
it('should return a hex number value type', function() {
const node = parse('0x0123456789abcdef');
expect(publish(node)).to.equal('0x0123456789abcdef');
});
});
it('should return a record type with an entry', function() {
const node = parse('{myNum}');
expect(publish(node)).to.equal('{myNum}');
describe('Wildcard types', function () {
it('should return an all type', function() {
const node = parse('*');
expect(publish(node)).to.equal('*');
});
it('should return an unknown type', function() {
const node = parse('?');
expect(publish(node)).to.equal('?');
});
});
describe('Generics', function () {
it('should return a generic type with a parameter', function() {
const node = parse('Array.<string>');
expect(publish(node)).to.equal('Array.<string>');
});
it('should return a record type with 2 entries', function() {
const node = parse('{myNum: number, myObject}');
expect(publish(node)).to.equal('{myNum: number, myObject}');
});
it('should return a generic type with 2 parameters', function() {
const node = parse('Object.<string, number>');
expect(publish(node)).to.equal('Object.<string, number>');
});
it('should return a tuple type', function() {
const node = parse('[]');
expect(publish(node)).to.equal('[]');
it('should return a JsDoc-formal generic type', function() {
const node = parse('String[]');
expect(publish(node)).to.equal('String[]');
});
});
describe('Record types', function () {
it('should return a record type with an entry', function() {
const node = parse('{myNum}');
expect(publish(node)).to.equal('{myNum}');
});
it('should return a tuple type with an entry', function() {
const node = parse('[number]');
expect(publish(node)).to.equal('[number]');
});
it('should return a record type with 2 entries', function() {
const node = parse('{myNum: number, myObject}');
expect(publish(node)).to.equal('{myNum: number, myObject}');
});
it('should return a tuple type with 2 entries', function() {
const node = parse('[number, MyObject]');
expect(publish(node)).to.equal('[number, MyObject]');
});
it('should return a quoted record type key', function() {
const node = parse('{"myNum": number, "myObject"}');
expect(publish(node)).to.equal('{"myNum": number, "myObject"}');
});
it('should return a quoted record type key (single quotes)', function() {
const node = parse("{'myNum': number, 'myObject'}");
expect(publish(node)).to.equal("{'myNum': number, 'myObject'}");
});
it('should return a generic type has a parameter as a record type', function() {
const node = parse('Array<{length}>');
expect(publish(node)).to.equal('Array<{length}>');
});
it('should return a quoted record type key with escaped quote', function() {
const node = parse('{"my\\"Num": number, "myObject"}');
expect(publish(node)).to.equal('{"my\\"Num": number, "myObject"}');
});
it('should return a quoted record type key with single extra backslash for odd count backslash series not before a quote', function() {
const node = parse('{"\\Odd count backslash sequence not before a quote\\add\\\\\\one backslash\\.": number, "myObject"}');
expect(publish(node)).to.equal('{"\\\\Odd count backslash sequence not before a quote\\\\add\\\\\\\\one backslash\\\\.": number, "myObject"}');
});
it('should return a generic type has a parameter as a tuple type', function() {
const node = parse('Array<[string, number]>');
expect(publish(node)).to.equal('Array<[string, number]>');
it('should return a quoted record type key without adding backslashes for escaped backslash sequences (i.e., even count)', function() {
const node = parse('{"\\\\Even count (escaped)\\\\\\\\backslash sequences\\\\remain\\\\": number, "myObject"}');
expect(publish(node)).to.equal('{"\\\\Even count (escaped)\\\\\\\\backslash sequences\\\\remain\\\\": number, "myObject"}');
});
});
describe('Tuple types', function () {
it('should return a tuple type', function() {
const node = parse('[]');
expect(publish(node)).to.equal('[]');
});
it('should return a nullable type has a nullable type operator on the head', function() {
const node = parse('?number');
expect(publish(node)).to.equal('?number');
});
it('should return a tuple type with an entry', function() {
const node = parse('[number]');
expect(publish(node)).to.equal('[number]');
});
it('should return a nullable type has a nullable type operator on the tail', function() {
const node = parse('goog.ui.Component?');
expect(publish(node)).to.equal('?goog.ui.Component');
});
it('should return a tuple type with 2 entries', function() {
const node = parse('[number, MyObject]');
expect(publish(node)).to.equal('[number, MyObject]');
});
it('should return a non-nullable type has a nullable type operator on the head', function() {
const node = parse('!Object');
expect(publish(node)).to.equal('!Object');
});
it('should return a generic type with a parameter as a record type', function() {
const node = parse('Array<{length}>');
expect(publish(node)).to.equal('Array<{length}>');
});
it('should return a non-nullable type has a nullable type operator on the tail', function() {
const node = parse('Object!');
expect(publish(node)).to.equal('!Object');
it('should return a generic type with a parameter as a tuple type', function() {
const node = parse('Array<[string, number]>');
expect(publish(node)).to.equal('Array<[string, number]>');
});
});
describe('Function/Constructor/Arrow types', function () {
it('should return a function type', function() {
const node = parse('Function');
expect(publish(node)).to.equal('Function');
});
it('should return a function type', function() {
const node = parse('Function');
expect(publish(node)).to.equal('Function');
});
it('should return a function type with no parameters', function() {
const node = parse('function()');
expect(publish(node)).to.equal('function()');
});
it('should return a function type has no parameters', function() {
const node = parse('function()');
expect(publish(node)).to.equal('function()');
});
it('should return a function type with a parameter', function() {
const node = parse('function(string)');
expect(publish(node)).to.equal('function(string)');
});
it('should return a function type has a parameter', function() {
const node = parse('function(string)');
expect(publish(node)).to.equal('function(string)');
});
it('should return a function type with 2 parameters', function() {
const node = parse('function(string, boolean)');
expect(publish(node)).to.equal('function(string, boolean)');
});
it('should return a function type has 2 parameters', function() {
const node = parse('function(string, boolean)');
expect(publish(node)).to.equal('function(string, boolean)');
});
it('should return a function type with a return', function() {
const node = parse('function(): number');
expect(publish(node)).to.equal('function(): number');
});
it('should return a function type has a return', function() {
const node = parse('function(): number');
expect(publish(node)).to.equal('function(): number');
});
it('should return a function type with a context', function() {
const node = parse('function(this:goog.ui.Menu, string)');
expect(publish(node)).to.equal('function(this: goog.ui.Menu, string)');
});
it('should return a function type has a context', function() {
const node = parse('function(this:goog.ui.Menu, string)');
expect(publish(node)).to.equal('function(this: goog.ui.Menu, string)');
});
it('should return a constructor type', function() {
const node = parse('function(new:goog.ui.Menu, string)');
expect(publish(node)).to.equal('function(new: goog.ui.Menu, string)');
});
it('should return a constructor type', function() {
const node = parse('function(new:goog.ui.Menu, string)');
expect(publish(node)).to.equal('function(new: goog.ui.Menu, string)');
});
it('should return a function type with a variable parameter', function() {
const node = parse('function(string, ...number): number');
expect(publish(node)).to.equal('function(string, ...number): number');
});
it('should return a function type has a variable parameter', function() {
const node = parse('function(string, ...number): number');
expect(publish(node)).to.equal('function(string, ...number): number');
});
it('should return a function type having parameters with some type operators', function() {
const node = parse('function(?string=, number=)');
expect(publish(node)).to.equal('function(?string=, number=)');
});
it('should return a function type has parameters have some type operators', function() {
const node = parse('function(?string=, number=)');
expect(publish(node)).to.equal('function(?string=, number=)');
});
it('should return an arrow type with no parameters', function() {
const node = parse('() => string');
expect(publish(node)).to.equal('() => string');
});
it('should return an arrow type with no parameters', function() {
const node = parse('() => string');
expect(publish(node)).to.equal('() => string');
});
it('should return an arrow type with two parameters', function() {
const node = parse('(x: true, y: false) => string');
expect(publish(node)).to.equal('(x: true, y: false) => string');
});
it('should return an arrow type with two parameters', function() {
const node = parse('(x: true, y: false) => string');
expect(publish(node)).to.equal('(x: true, y: false) => string');
});
it('should return an arrow type with one parameter', function() {
const node = parse('(x: true) => string');
expect(publish(node)).to.equal('(x: true) => string');
});
it('should return an arrow type with one parameter', function() {
const node = parse('(x: true) => string');
expect(publish(node)).to.equal('(x: true) => string');
});
it('should return an arrow type with one variadic parameter', function() {
const node = parse('(...x: any[]) => string');
expect(publish(node)).to.equal('(...x: any[]) => string');
});
it('should return an arrow type with one variadic parameter', function() {
const node = parse('(...x: any[]) => string');
expect(publish(node)).to.equal('(...x: any[]) => string');
});
it('should return a construct signature with one parameter', function() {
const node = parse('new (x: true) => string');
expect(publish(node)).to.equal('new (x: true) => string');
});
it('should return a construct signature with one parameter', function() {
const node = parse('new (x: true) => string');
expect(publish(node)).to.equal('new (x: true) => string');
it('should return a goog.ui.Component#forEachChild', function() {
const node = parse('function(this:T,?,number):?');
expect(publish(node)).to.equal('function(this: T, ?, number): ?');
});
});
it('should return a goog.ui.Component#forEachChild', function() {
const node = parse('function(this:T,?,number):?');
expect(publish(node)).to.equal('function(this: T, ?, number): ?');
});
describe('BroadNamepathExpr types', function () {
describe('Single component', function () {
it('should return a global type name', function() {
const node = parse('Window');
expect(publish(node)).to.equal('Window');
});
});
describe('Multipart', function () {
it('should return a user-defined type name', function() {
const node = parse('goog.ui.Menu');
expect(publish(node)).to.equal('goog.ui.Menu');
});
it('should return a variable type', function() {
const node = parse('...number');
expect(publish(node)).to.equal('...number');
});
it('should return a quoted `MemberName` type', function() {
const node = parse('namespace."memberNameValue"');
expect(publish(node)).to.equal('namespace."memberNameValue"');
});
it('should return a quoted `MemberName` type (single quotes)', function() {
const node = parse("namespace.'memberNameValue'");
expect(publish(node)).to.equal("namespace.'memberNameValue'");
});
it('should return an optional type has an optional type operator on the head', function() {
const node = parse('=number');
expect(publish(node)).to.equal('number=');
});
it('should return a quoted `MemberName` type with escaped quote', function() {
const node = parse('namespace."member name \\"Value"');
expect(publish(node)).to.equal('namespace."member name \\"Value"');
});
it('should return a quoted `MemberName` type with single extra backslash for odd count backslash series not before a quote', function() {
const node = parse('namespace."\\Odd count backslash sequence not before a quote\\add\\\\\\one backslash\\."');
expect(publish(node)).to.equal('namespace."\\\\Odd count backslash sequence not before a quote\\\\add\\\\\\\\one backslash\\\\."');
});
it('should return an optional type has an optional type operator on the tail', function() {
const node = parse('number=');
expect(publish(node)).to.equal('number=');
});
it('should return a quoted `MemberName` type without adding backslashes for escaped backslash sequences (i.e., even count)', function() {
const node = parse('namespace."\\\\Even count (escaped)\\\\\\\\backslash sequences\\\\remain\\\\"');
expect(publish(node)).to.equal('namespace."\\\\Even count (escaped)\\\\\\\\backslash sequences\\\\remain\\\\"');
});
});
describe('external', function () {
it('should return an external node type', function() {
const node = parse('external:string');
expect(publish(node)).to.equal('external:string');
});
it('should return an external node type with an instance member method', function() {
const node = parse('external : String#rot13');
expect(publish(node)).to.equal('external:String#rot13');
});
it('should return a quoted external node type', function() {
const node = parse('external:"jQuery.fn"');
expect(publish(node)).to.equal('external:"jQuery.fn"');
});
it('should return a quoted external node type with a static member method and event', function() {
const node = parse('external:"jQuery.fn".someMethod#event:abc');
expect(publish(node)).to.equal('external:"jQuery.fn".someMethod#event:abc');
});
});
it('should return an all type', function() {
const node = parse('*');
expect(publish(node)).to.equal('*');
});
describe('module', function () {
it('should return a module type', function() {
const node = parse('module:foo/bar');
expect(publish(node)).to.equal('module:foo/bar');
});
it('should return an unknown type', function() {
const node = parse('?');
expect(publish(node)).to.equal('?');
});
it('should return a module type with member', function() {
const node = parse('module:foo/bar#abc');
expect(publish(node)).to.equal('module:foo/bar#abc');
});
it('should return a module type with event member', function() {
const node = parse('module:foo/bar#event:abc');
expect(publish(node)).to.equal('module:foo/bar#event:abc');
});
it('should return an undefined type with an "undefined" keyword', function() {
const node = parse('undefined');
expect(publish(node)).to.equal('undefined');
});
it('should return a module type with a prefix nullable type operator', function() {
const node = parse('?module:foo/bar');
expect(publish(node)).to.equal('?module:foo/bar');
});
it('should return a null type with an "null" keyword', function() {
const node = parse('null');
expect(publish(node)).to.equal('null');
});
it('should return a module type with a postfix nullable type operator', function() {
const node = parse('module:foo/bar?');
expect(publish(node)).to.equal('?module:foo/bar');
});
it('should return a module type', function() {
const node = parse('module:foo/bar');
expect(publish(node)).to.equal('module:foo/bar');
});
it('should return a module type with a generic type operator', function() {
// Because the new generic type syntax was arrived, the old type generic
// with the module keyword is not equivalent to the legacy behavior.
//
// For example, we get 2 parts as 'module:foo/bar.' and '<string>', when
// the following type expression are arrived.
// const node = parse('module:foo/bar.<string>');
const node = parse('module:foo/bar<string>');
expect(publish(node)).to.equal('module:foo/bar<string>');
});
it('should return a module type with member', function() {
const node = parse('module:foo/bar#abc');
expect(publish(node)).to.equal('module:foo/bar#abc');
});
it('should return a quoted module type', function() {
const node = parse('module:"module/path".member');
expect(publish(node)).to.equal('module:"module/path".member');
});
it('should return a module type with event member', function() {
const node = parse('module:foo/bar#event:abc');
expect(publish(node)).to.equal('module:foo/bar#event:abc');
});
it('should return a quoted module type (single quotes)', function() {
const node = parse("module:'module/path'.member");
expect(publish(node)).to.equal("module:'module/path'.member");
});
it('should return a quoted module type with escaped quote', function() {
const node = parse('module:"module/path\\"Value".member');
expect(publish(node)).to.equal('module:"module/path\\"Value".member');
});
it('should return a module type with a prefix nullable type operator', function() {
const node = parse('?module:foo/bar');
expect(publish(node)).to.equal('?module:foo/bar');
it('should return a quoted module type with single extra backslash for odd count backslash series not before a quote', function() {
const node = parse('module:"\\Odd/count/backslash/sequence/not/before/a/quote\\add\\\\\\one/backslash\\.".member');
expect(publish(node)).to.equal('module:"\\\\Odd/count/backslash/sequence/not/before/a/quote\\\\add\\\\\\\\one/backslash\\\\.".member');
});
it('should return a quoted module type without adding backslashes for escaped backslash sequences (i.e., even count)', function() {
const node = parse('module:"\\\\Even/count/(escaped)\\\\\\\\backslash/sequences\\\\remain\\\\".member');
expect(publish(node)).to.equal('module:"\\\\Even/count/(escaped)\\\\\\\\backslash/sequences\\\\remain\\\\".member');
});
});
});
describe('Types with modifiers', function () {
it('should return a variable type', function () {
const node = parse('...number');
expect(publish(node)).to.equal('...number');
});
it('should return a module type with a postfix nullable type operator', function() {
const node = parse('module:foo/bar?');
expect(publish(node)).to.equal('?module:foo/bar');
});
it('should return an optional type with an optional type operator on the head', function() {
const node = parse('=number');
expect(publish(node)).to.equal('number=');
});
it('should return a string value type', function() {
const node = parse('"stringValue"');
expect(publish(node)).to.equal('"stringValue"');
});
it('should return an optional type with an optional type operator on the tail', function() {
const node = parse('number=');
expect(publish(node)).to.equal('number=');
});
it('should return a number value type', function() {
const node = parse('0123456789');
expect(publish(node)).to.equal('0123456789');
});
it('should return a nullable type with a nullable type operator on the head', function() {
const node = parse('?number');
expect(publish(node)).to.equal('?number');
});
it('should return a bin number value type', function() {
const node = parse('0b01');
expect(publish(node)).to.equal('0b01');
});
it('should return a nullable type with a nullable type operator on the tail', function() {
const node = parse('goog.ui.Component?');
expect(publish(node)).to.equal('?goog.ui.Component');
});
it('should return an oct number value type', function() {
const node = parse('0o01234567');
expect(publish(node)).to.equal('0o01234567');
});
it('should return a non-nullable type with a nullable type operator on the head', function() {
const node = parse('!Object');
expect(publish(node)).to.equal('!Object');
});
it('should return a hex number value type', function() {
const node = parse('0x0123456789abcdef');
expect(publish(node)).to.equal('0x0123456789abcdef');
it('should return a non-nullable type with a nullable type operator on the tail', function() {
const node = parse('Object!');
expect(publish(node)).to.equal('!Object');
});
});
describe('Type combinations', function () {
it('should return a formal type union', function() {
const node = parse('(number|boolean)');
expect(publish(node)).to.equal('(number|boolean)');
});
it('should return an external node type', function() {
const node = parse('external:string');
expect(publish(node)).to.equal('external:string');
});
it('should return a module type with a generic type operator', function() {
// Because the new generic type syntax was arrived, the old type generic
// with the module keyword is not equivalent to the legacy behavior.
//
// For example, we get 2 parts as 'module:foo/bar.' and '<string>', when
// the following type expression are arrived.
// const node = parse('module:foo/bar.<string>');
const node = parse('module:foo/bar<string>');
expect(publish(node)).to.equal('module:foo/bar<string>');
it('should return a informal type union', function() {
const node = parse('number|boolean');
expect(publish(node)).to.equal('number|boolean');
});
});
describe('Types with operations', function () {
it('should return a type query node', function() {
const node = parse('typeof x');
expect(publish(node)).to.equal('typeof x');
});
it('should can take a custom publisher by the 2nd argument', function() {
const ast = {
type: 'NAME',
name: 'MyClass',
};
it('should return a key query node', function() {
const node = parse('keyof x');
expect(publish(node)).to.equal('keyof x');
})
const customPublisher = createDefaultPublisher();
customPublisher.NAME = function(node) {
return '<a href="./types/' + node.name + '.html">' + node.name + '</a>';
};
const string = publish(ast, customPublisher);
expect(string).to.equal('<a href="./types/MyClass.html">MyClass</a>');
it('should return an import type node', function() {
const node = parse('import("./lodash4ever")');
expect(publish(node)).to.equal('import("./lodash4ever")');
});
});
});
'use strict';
const {expect} = require('chai');
const entries = require('object.entries-ponyfill');
const NodeType = require('../lib/NodeType.js');
const {traverse} = require('../lib/traversing.js');
/** @typedef {{type: import('../lib/NodeType').Type}} Node */
describe('traversing', function() {
const testCases = {
'should visit a name node': {
given: createNameNode('name'),
then: [
['enter', NodeType.NAME, null, null],
['leave', NodeType.NAME, null, null],
],
},
const testCaseGroups = {
'Primitive types': {
'should visit a string value node': {
given: { type: NodeType.STRING_VALUE, value: 'stringValue' },
then: [
['enter', NodeType.STRING_VALUE, null, null],
['leave', NodeType.STRING_VALUE, null, null],
],
},
'should visit a member node': {
given: createMemberNode('child', createNameNode('owner')),
then: [
['enter', NodeType.MEMBER, null, null],
['enter', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.MEMBER, null, null],
],
'should visit a number value node': {
given: { type: NodeType.NUMBER_VALUE, value: 'numberValue' },
then: [
['enter', NodeType.NUMBER_VALUE, null, null],
['leave', NodeType.NUMBER_VALUE, null, null],
],
},
},
'Wildcard types': {
'should visit an any node': {
given: {
type: NodeType.ANY,
},
then: [
['enter', NodeType.ANY, null, null],
['leave', NodeType.ANY, null, null],
],
},
'should visit a nested member node': {
given: createMemberNode('superchild', createMemberNode('child', createNameNode('owner'))),
then: [
['enter', NodeType.MEMBER, null, null],
['enter', NodeType.MEMBER, 'owner', NodeType.MEMBER],
['enter', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.MEMBER, 'owner', NodeType.MEMBER],
['leave', NodeType.MEMBER, null, null],
],
'should visit an unknown node': {
given: {
type: NodeType.UNKNOWN,
},
then: [
['enter', NodeType.UNKNOWN, null, null],
['leave', NodeType.UNKNOWN, null, null],
],
},
},
'Generic types': {
'should visit a generic node that is empty': {
given: {
type: NodeType.GENERIC,
subject: createNameNode('subject'),
objects: [],
},
then: [
['enter', NodeType.GENERIC, null, null],
['enter', NodeType.NAME, 'subject', NodeType.GENERIC],
['leave', NodeType.NAME, 'subject', NodeType.GENERIC],
['leave', NodeType.GENERIC, null, null],
],
},
'should visit an union node': {
given: createUnionNode(createNameNode('left'), createNameNode('right')),
then: [
['enter', NodeType.UNION, null, null],
['enter', NodeType.NAME, 'left', NodeType.UNION],
['leave', NodeType.NAME, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.UNION, null, null],
],
'should visit a generic node that has multiple objects': {
given: {
type: NodeType.GENERIC,
subject: createNameNode('subject'),
objects: [
createNameNode('object1'),
createNameNode('object2'),
],
},
then: [
['enter', NodeType.GENERIC, null, null],
['enter', NodeType.NAME, 'subject', NodeType.GENERIC],
['leave', NodeType.NAME, 'subject', NodeType.GENERIC],
['enter', NodeType.NAME, 'objects', NodeType.GENERIC],
['leave', NodeType.NAME, 'objects', NodeType.GENERIC],
['enter', NodeType.NAME, 'objects', NodeType.GENERIC],
['leave', NodeType.NAME, 'objects', NodeType.GENERIC],
['leave', NodeType.GENERIC, null, null],
],
},
},
'Record types': {
'should visit a record node that is empty': {
given: {
type: NodeType.RECORD,
entries: [],
},
then: [
['enter', NodeType.RECORD, null, null],
['leave', NodeType.RECORD, null, null],
],
},
'should visit a type query node': {
given: createTypeQueryNode(createNameNode('t')),
then: [
['enter', NodeType.TYPE_QUERY, null, null],
['enter', NodeType.NAME, 'name', NodeType.TYPE_QUERY],
['leave', NodeType.NAME, 'name', NodeType.TYPE_QUERY],
['leave', NodeType.TYPE_QUERY, null, null],
],
'should visit a record node that has multiple entries': {
given: {
type: NodeType.RECORD,
entries: [
createRecordEntry('key1', createNameNode('key1')),
createRecordEntry('key2', createNameNode('key2')),
],
},
then: [
['enter', NodeType.RECORD, null, null],
['enter', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['enter', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['enter', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['enter', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['leave', NodeType.RECORD, null, null],
],
},
},
'Tuple types': {
'should visit a tuple node that is empty': {
given: {
type: NodeType.TUPLE,
entries: [],
},
then: [
['enter', NodeType.TUPLE, null, null],
['leave', NodeType.TUPLE, null, null],
],
},
'should visit an import type node': {
given: createImportNode(createStringLiteral('jquery')),
then: [
['enter', NodeType.IMPORT, null, null],
['enter', NodeType.STRING_VALUE, 'path', NodeType.IMPORT],
['leave', NodeType.STRING_VALUE, 'path', NodeType.IMPORT],
['leave', NodeType.IMPORT, null, null],
],
'should visit a tuple node that has multiple entries': {
given: {
type: NodeType.TUPLE,
entries: [
createNameNode('object1'),
createNameNode('object2'),
],
},
then: [
['enter', NodeType.TUPLE, null, null],
['enter', NodeType.NAME, 'entries', NodeType.TUPLE],
['leave', NodeType.NAME, 'entries', NodeType.TUPLE],
['enter', NodeType.NAME, 'entries', NodeType.TUPLE],
['leave', NodeType.NAME, 'entries', NodeType.TUPLE],
['leave', NodeType.TUPLE, null, null],
],
},
},
'Function/Constructor/Arrow types': {
'should visit a function node that has no params and no returns': {
given: {
type: NodeType.FUNCTION,
params: [],
returns: null,
this: null,
new: null,
},
then: [
['enter', NodeType.FUNCTION, null, null],
['leave', NodeType.FUNCTION, null, null],
],
},
'should visit a nested union node': {
given: createUnionNode(
createUnionNode(
createNameNode('left'),
createNameNode('middle')
),
createNameNode('right')
),
then: [
['enter', NodeType.UNION, null, null],
['enter', NodeType.UNION, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'left', NodeType.UNION],
['leave', NodeType.NAME, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.UNION, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.UNION, null, null],
],
},
'should visit a function node that has few params and a returns and "this" and "new"': {
given: {
type: NodeType.FUNCTION,
params: [
createNameNode('param1'),
createNameNode('param2'),
],
returns: createNameNode('return'),
this: createNameNode('this'),
new: createNameNode('new'),
},
then: [
['enter', NodeType.FUNCTION, null, null],
['enter', NodeType.NAME, 'params', NodeType.FUNCTION],
['leave', NodeType.NAME, 'params', NodeType.FUNCTION],
['enter', NodeType.NAME, 'params', NodeType.FUNCTION],
['leave', NodeType.NAME, 'params', NodeType.FUNCTION],
['enter', NodeType.NAME, 'returns', NodeType.FUNCTION],
['leave', NodeType.NAME, 'returns', NodeType.FUNCTION],
['enter', NodeType.NAME, 'this', NodeType.FUNCTION],
['leave', NodeType.NAME, 'this', NodeType.FUNCTION],
['enter', NodeType.NAME, 'new', NodeType.FUNCTION],
['leave', NodeType.NAME, 'new', NodeType.FUNCTION],
['leave', NodeType.FUNCTION, null, null],
],
},
'should visit a variadic node': {
given: { type: NodeType.VARIADIC, value: createNameNode('variadic') },
then: [
['enter', NodeType.VARIADIC, null, null],
['enter', NodeType.NAME, 'value', NodeType.VARIADIC],
['leave', NodeType.NAME, 'value', NodeType.VARIADIC],
['leave', NodeType.VARIADIC, null, null],
],
},
'should visit an arrow function that has two params and a returns': {
given: {
type: NodeType.ARROW,
params: [
{ type: NodeType.NAMED_PARAMETER, name: 'param1', typeName: createNameNode('type1') },
{ type: NodeType.NAMED_PARAMETER, name: 'param2', typeName: createNameNode('type2') },
],
returns: createNameNode('return'),
},
then: [
['enter', NodeType.ARROW, null, null],
['enter', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.ARROW, null, null],
],
},
'should visit a record node that is empty': {
given: {
type: NodeType.RECORD,
entries: [],
'should visit an arrow function that has one variadic param and a returns': {
given: {
type: NodeType.ARROW,
params: [
{
type: NodeType.VARIADIC,
value: {
type: NodeType.NAMED_PARAMETER,
name: 'param1',
typeName: createNameNode('type1'),
},
},
],
returns: createNameNode('return'),
},
then: [
['enter', NodeType.ARROW, null, null],
['enter', NodeType.VARIADIC, 'params', NodeType.ARROW],
['enter', NodeType.NAMED_PARAMETER, 'value', NodeType.VARIADIC],
['enter', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAMED_PARAMETER, 'value', NodeType.VARIADIC],
['leave', NodeType.VARIADIC, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.ARROW, null, null],
],
},
then: [
['enter', NodeType.RECORD, null, null],
['leave', NodeType.RECORD, null, null],
],
},
'NamepathExpr types': {
'should visit a name node': {
given: createNameNode('name'),
then: [
['enter', NodeType.NAME, null, null],
['leave', NodeType.NAME, null, null],
],
},
'should visit a record node that has multiple entries': {
given: {
type: NodeType.RECORD,
entries: [
createRecordEntry('key1', createNameNode('key1')),
createRecordEntry('key2', createNameNode('key2')),
'should visit a member node': {
given: createMemberNode('child', createNameNode('owner')),
then: [
['enter', NodeType.MEMBER, null, null],
['enter', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.MEMBER, null, null],
],
},
then: [
['enter', NodeType.RECORD, null, null],
['enter', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['enter', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['enter', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['enter', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.NAME, 'value', NodeType.RECORD_ENTRY],
['leave', NodeType.RECORD_ENTRY, 'entries', NodeType.RECORD],
['leave', NodeType.RECORD, null, null],
],
},
'should visit a tuple node that is empty': {
given: {
type: NodeType.TUPLE,
entries: [],
'should visit a nested member node': {
given: createMemberNode('superchild', createMemberNode('child', createNameNode('owner'))),
then: [
['enter', NodeType.MEMBER, null, null],
['enter', NodeType.MEMBER, 'owner', NodeType.MEMBER],
['enter', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.MEMBER],
['leave', NodeType.MEMBER, 'owner', NodeType.MEMBER],
['leave', NodeType.MEMBER, null, null],
],
},
then: [
['enter', NodeType.TUPLE, null, null],
['leave', NodeType.TUPLE, null, null],
],
},
'should visit a tuple node that has multiple entries': {
given: {
type: NodeType.TUPLE,
entries: [
createNameNode('object1'),
createNameNode('object2'),
'should visit an inner member node': {
given: createInnerMemberNode('child', createNameNode('owner')),
then: [
['enter', NodeType.INNER_MEMBER, null, null],
['enter', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.INNER_MEMBER, null, null],
],
},
then: [
['enter', NodeType.TUPLE, null, null],
['enter', NodeType.NAME, 'entries', NodeType.TUPLE],
['leave', NodeType.NAME, 'entries', NodeType.TUPLE],
['enter', NodeType.NAME, 'entries', NodeType.TUPLE],
['leave', NodeType.NAME, 'entries', NodeType.TUPLE],
['leave', NodeType.TUPLE, null, null],
],
},
'should visit a generic node that is empty': {
given: {
type: NodeType.GENERIC,
subject: createNameNode('subject'),
objects: [],
'should visit a nested inner member node': {
given: createInnerMemberNode('superchild',
createInnerMemberNode('child', createNameNode('owner'))),
then: [
['enter', NodeType.INNER_MEMBER, null, null],
['enter', NodeType.INNER_MEMBER, 'owner', NodeType.INNER_MEMBER],
['enter', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.INNER_MEMBER, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.INNER_MEMBER, null, null],
],
},
then: [
['enter', NodeType.GENERIC, null, null],
['enter', NodeType.NAME, 'subject', NodeType.GENERIC],
['leave', NodeType.NAME, 'subject', NodeType.GENERIC],
['leave', NodeType.GENERIC, null, null],
],
},
'should visit a generic node that has multiple objects': {
given: {
type: NodeType.GENERIC,
subject: createNameNode('subject'),
objects: [
createNameNode('object1'),
createNameNode('object2'),
'should visit an instance member node': {
given: createInstanceMemberNode('child', createNameNode('owner')),
then: [
['enter', NodeType.INSTANCE_MEMBER, null, null],
['enter', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.INSTANCE_MEMBER, null, null],
],
},
then: [
['enter', NodeType.GENERIC, null, null],
['enter', NodeType.NAME, 'subject', NodeType.GENERIC],
['leave', NodeType.NAME, 'subject', NodeType.GENERIC],
['enter', NodeType.NAME, 'objects', NodeType.GENERIC],
['leave', NodeType.NAME, 'objects', NodeType.GENERIC],
['enter', NodeType.NAME, 'objects', NodeType.GENERIC],
['leave', NodeType.NAME, 'objects', NodeType.GENERIC],
['leave', NodeType.GENERIC, null, null],
],
},
'should visit a module node': {
given: {
type: NodeType.MODULE,
value: createFilePathNode('module'),
'should visit a nested instance member node': {
given: createInstanceMemberNode('superchild',
createInstanceMemberNode('child', createNameNode('owner'))),
then: [
['enter', NodeType.INSTANCE_MEMBER, null, null],
['enter', NodeType.INSTANCE_MEMBER, 'owner', NodeType.INSTANCE_MEMBER],
['enter', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.INSTANCE_MEMBER, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.INSTANCE_MEMBER, null, null],
],
},
then: [
['enter', NodeType.MODULE, null, null],
['enter', NodeType.FILE_PATH, 'value', NodeType.MODULE],
['leave', NodeType.FILE_PATH, 'value', NodeType.MODULE],
['leave', NodeType.MODULE, null, null],
],
},
'should visit an optional node': {
given: {
type: NodeType.OPTIONAL,
value: createNameNode('optional'),
'External': {
'should visit an external node': {
given: { type: NodeType.EXTERNAL, value: createNameNode('external') },
then: [
['enter', NodeType.EXTERNAL, null, null],
['enter', NodeType.NAME, 'value', NodeType.EXTERNAL],
['leave', NodeType.NAME, 'value', NodeType.EXTERNAL],
['leave', NodeType.EXTERNAL, null, null],
],
},
then: [
['enter', NodeType.OPTIONAL, null, null],
['enter', NodeType.NAME, 'value', NodeType.OPTIONAL],
['leave', NodeType.NAME, 'value', NodeType.OPTIONAL],
['leave', NodeType.OPTIONAL, null, null],
],
},
'should visit a nullable node': {
given: {
type: NodeType.NULLABLE,
value: createNameNode('nullable'),
'Modules': {
'should visit a module node': {
given: {
type: NodeType.MODULE,
value: createFilePathNode('module'),
},
then: [
['enter', NodeType.MODULE, null, null],
['enter', NodeType.FILE_PATH, 'value', NodeType.MODULE],
['leave', NodeType.FILE_PATH, 'value', NodeType.MODULE],
['leave', NodeType.MODULE, null, null],
],
},
then: [
['enter', NodeType.NULLABLE, null, null],
['enter', NodeType.NAME, 'value', NodeType.NULLABLE],
['leave', NodeType.NAME, 'value', NodeType.NULLABLE],
['leave', NodeType.NULLABLE, null, null],
],
},
'should visit a non-nullable node': {
given: {
type: NodeType.NOT_NULLABLE,
value: createNameNode('not_nullable'),
'Types with modifiers': {
'should visit a variadic node': {
given: { type: NodeType.VARIADIC, value: createNameNode('variadic') },
then: [
['enter', NodeType.VARIADIC, null, null],
['enter', NodeType.NAME, 'value', NodeType.VARIADIC],
['leave', NodeType.NAME, 'value', NodeType.VARIADIC],
['leave', NodeType.VARIADIC, null, null],
],
},
then: [
['enter', NodeType.NOT_NULLABLE, null, null],
['enter', NodeType.NAME, 'value', NodeType.NOT_NULLABLE],
['leave', NodeType.NAME, 'value', NodeType.NOT_NULLABLE],
['leave', NodeType.NOT_NULLABLE, null, null],
],
},
'should visit an optional node': {
given: {
type: NodeType.OPTIONAL,
value: createNameNode('optional'),
},
then: [
['enter', NodeType.OPTIONAL, null, null],
['enter', NodeType.NAME, 'value', NodeType.OPTIONAL],
['leave', NodeType.NAME, 'value', NodeType.OPTIONAL],
['leave', NodeType.OPTIONAL, null, null],
],
},
'should visit a function node that has no params and no returns': {
given: {
type: NodeType.FUNCTION,
params: [],
returns: null,
this: null,
new: null,
'should visit a nullable node': {
given: {
type: NodeType.NULLABLE,
value: createNameNode('nullable'),
},
then: [
['enter', NodeType.NULLABLE, null, null],
['enter', NodeType.NAME, 'value', NodeType.NULLABLE],
['leave', NodeType.NAME, 'value', NodeType.NULLABLE],
['leave', NodeType.NULLABLE, null, null],
],
},
then: [
['enter', NodeType.FUNCTION, null, null],
['leave', NodeType.FUNCTION, null, null],
],
},
'should visit a function node that has few params and a returns and "this" and "new"': {
given: {
type: NodeType.FUNCTION,
params: [
createNameNode('param1'),
createNameNode('param2'),
'should visit a non-nullable node': {
given: {
type: NodeType.NOT_NULLABLE,
value: createNameNode('not_nullable'),
},
then: [
['enter', NodeType.NOT_NULLABLE, null, null],
['enter', NodeType.NAME, 'value', NodeType.NOT_NULLABLE],
['leave', NodeType.NAME, 'value', NodeType.NOT_NULLABLE],
['leave', NodeType.NOT_NULLABLE, null, null],
],
returns: createNameNode('return'),
this: createNameNode('this'),
new: createNameNode('new'),
},
then: [
['enter', NodeType.FUNCTION, null, null],
['enter', NodeType.NAME, 'params', NodeType.FUNCTION],
['leave', NodeType.NAME, 'params', NodeType.FUNCTION],
['enter', NodeType.NAME, 'params', NodeType.FUNCTION],
['leave', NodeType.NAME, 'params', NodeType.FUNCTION],
['enter', NodeType.NAME, 'returns', NodeType.FUNCTION],
['leave', NodeType.NAME, 'returns', NodeType.FUNCTION],
['enter', NodeType.NAME, 'this', NodeType.FUNCTION],
['leave', NodeType.NAME, 'this', NodeType.FUNCTION],
['enter', NodeType.NAME, 'new', NodeType.FUNCTION],
['leave', NodeType.NAME, 'new', NodeType.FUNCTION],
['leave', NodeType.FUNCTION, null, null],
],
},
'should visit an arrow function that has two params and a returns': {
given: {
type: NodeType.ARROW,
params: [
{ type: NodeType.NAMED_PARAMETER, name: 'param1', typeName: createNameNode('type1') },
{ type: NodeType.NAMED_PARAMETER, name: 'param2', typeName: createNameNode('type2') },
'Type combinations': {
'should visit a union node': {
given: createUnionNode(createNameNode('left'), createNameNode('right')),
then: [
['enter', NodeType.UNION, null, null],
['enter', NodeType.NAME, 'left', NodeType.UNION],
['leave', NodeType.NAME, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.UNION, null, null],
],
returns: createNameNode('return'),
},
then: [
['enter', NodeType.ARROW, null, null],
['enter', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAMED_PARAMETER, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.ARROW, null, null],
],
'should visit a nested union node': {
given: createUnionNode(
createUnionNode(
createNameNode('left'),
createNameNode('middle')
),
createNameNode('right')
),
then: [
['enter', NodeType.UNION, null, null],
['enter', NodeType.UNION, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'left', NodeType.UNION],
['leave', NodeType.NAME, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.UNION, 'left', NodeType.UNION],
['enter', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.NAME, 'right', NodeType.UNION],
['leave', NodeType.UNION, null, null],
],
},
},
'should visit an arrow function that has one variadic param and a returns': {
given: {
type: NodeType.ARROW,
params: [
{
type: NodeType.VARIADIC,
value: {
type: NodeType.NAMED_PARAMETER,
name: 'param1',
typeName: createNameNode('type1'),
},
},
'Types with operations': {
'should visit a type query node': {
given: createTypeQueryNode(createNameNode('t')),
then: [
['enter', NodeType.TYPE_QUERY, null, null],
['enter', NodeType.NAME, 'name', NodeType.TYPE_QUERY],
['leave', NodeType.NAME, 'name', NodeType.TYPE_QUERY],
['leave', NodeType.TYPE_QUERY, null, null],
],
returns: createNameNode('return'),
},
then: [
['enter', NodeType.ARROW, null, null],
['enter', NodeType.VARIADIC, 'params', NodeType.ARROW],
['enter', NodeType.NAMED_PARAMETER, 'value', NodeType.VARIADIC],
['enter', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAME, 'typeName', NodeType.NAMED_PARAMETER],
['leave', NodeType.NAMED_PARAMETER, 'value', NodeType.VARIADIC],
['leave', NodeType.VARIADIC, 'params', NodeType.ARROW],
['enter', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.NAME, 'returns', NodeType.ARROW],
['leave', NodeType.ARROW, null, null],
],
},
'should visit an any node': {
given: {
type: NodeType.ANY,
'should visit a key query node': {
given: createKeyQueryNode(createNameNode('t')),
then: [
['enter', NodeType.KEY_QUERY, null, null],
['enter', NodeType.NAME, 'value', NodeType.KEY_QUERY],
['leave', NodeType.NAME, 'value', NodeType.KEY_QUERY],
['leave', NodeType.KEY_QUERY, null, null],
],
},
then: [
['enter', NodeType.ANY, null, null],
['leave', NodeType.ANY, null, null],
],
},
'should visit an unknown node': {
given: {
type: NodeType.UNKNOWN,
'should visit an import type node': {
given: createImportNode(createStringLiteral('jquery')),
then: [
['enter', NodeType.IMPORT, null, null],
['enter', NodeType.STRING_VALUE, 'path', NodeType.IMPORT],
['leave', NodeType.STRING_VALUE, 'path', NodeType.IMPORT],
['leave', NodeType.IMPORT, null, null],
],
},
then: [
['enter', NodeType.UNKNOWN, null, null],
['leave', NodeType.UNKNOWN, null, null],
],
},
'should visit an inner member node': {
given: createInnerMemberNode('child', createNameNode('owner')),
then: [
['enter', NodeType.INNER_MEMBER, null, null],
['enter', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.INNER_MEMBER, null, null],
],
},
'should visit a nested inner member node': {
given: createInnerMemberNode('superchild',
createInnerMemberNode('child', createNameNode('owner'))),
then: [
['enter', NodeType.INNER_MEMBER, null, null],
['enter', NodeType.INNER_MEMBER, 'owner', NodeType.INNER_MEMBER],
['enter', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.INNER_MEMBER, 'owner', NodeType.INNER_MEMBER],
['leave', NodeType.INNER_MEMBER, null, null],
],
},
'should visit an instance member node': {
given: createInstanceMemberNode('child', createNameNode('owner')),
then: [
['enter', NodeType.INSTANCE_MEMBER, null, null],
['enter', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.INSTANCE_MEMBER, null, null],
],
},
'should visit a nested instance member node': {
given: createInstanceMemberNode('superchild',
createInstanceMemberNode('child', createNameNode('owner'))),
then: [
['enter', NodeType.INSTANCE_MEMBER, null, null],
['enter', NodeType.INSTANCE_MEMBER, 'owner', NodeType.INSTANCE_MEMBER],
['enter', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.NAME, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.INSTANCE_MEMBER, 'owner', NodeType.INSTANCE_MEMBER],
['leave', NodeType.INSTANCE_MEMBER, null, null],
],
},
'should visit a string value node': {
given: { type: NodeType.STRING_VALUE, value: 'stringValue' },
then: [
['enter', NodeType.STRING_VALUE, null, null],
['leave', NodeType.STRING_VALUE, null, null],
],
},
'should visit a number value node': {
given: { type: NodeType.NUMBER_VALUE, value: 'numberValue' },
then: [
['enter', NodeType.NUMBER_VALUE, null, null],
['leave', NodeType.NUMBER_VALUE, null, null],
],
},
'should visit an external node': {
given: { type: NodeType.EXTERNAL, value: createNameNode('external') },
then: [
['enter', NodeType.EXTERNAL, null, null],
['enter', NodeType.NAME, 'value', NodeType.EXTERNAL],
['leave', NodeType.NAME, 'value', NodeType.EXTERNAL],
['leave', NodeType.EXTERNAL, null, null],
],
},
};
Object.keys(testCases).forEach(function(testCaseName) {
const testCaseInfo = testCases[testCaseName];
entries(testCaseGroups).forEach(function ([testCaseGroup, testCases]) {
describe(testCaseGroup, function () {
entries(testCases).forEach(function([testCaseName, testCaseInfo]) {
it(testCaseName, function() {
const visitedOrder = [];
const onEnterSpy = createEventSpy('enter', visitedOrder);
const onLeaveSpy = createEventSpy('leave', visitedOrder);
it(testCaseName, function() {
const visitedOrder = [];
const onEnterSpy = createEventSpy('enter', visitedOrder);
const onLeaveSpy = createEventSpy('leave', visitedOrder);
traverse(testCaseInfo.given, onEnterSpy, onLeaveSpy);
traverse(testCaseInfo.given, onEnterSpy, onLeaveSpy);
expect(visitedOrder).to.deep.equal(testCaseInfo.then);
expect(visitedOrder).to.deep.equal(testCaseInfo.then);
});
});
});

@@ -485,2 +512,13 @@ });

/**
* @template {Node} T
* @param {T} value
*/
function createKeyQueryNode(value) {
return {
type: NodeType.KEY_QUERY,
value: value,
}
}
function createImportNode(path) {

@@ -496,2 +534,3 @@ return {

type: NodeType.STRING_VALUE,
quoteStyle: 'double',
string: string,

@@ -498,0 +537,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc