2021-10-28 11:49:37 +03:00

1256 lines
22 KiB
JavaScript

import parse from '../../src/parsers/javascript.js';
import removePosition from '../../src/remark-remove-position.js';
import { remark } from 'remark';
const remarkParse = remark().use(removePosition).parse;
import { visit } from 'unist-util-visit';
function pick(obj, props) {
if (Array.isArray(props)) {
return props.reduce(function (memo, prop) {
if (obj[prop] !== undefined) {
memo[prop] = obj[prop];
}
return memo;
}, {});
}
return obj[props];
}
function evaluate(fn, filename) {
return parse(
{
file: filename || 'test.js',
source: fn instanceof Function ? '(' + fn.toString() + ')' : fn
},
{}
);
}
function addJSDocTag(tree) {
visit(tree, 'link', function (node) {
node.jsdoc = true;
});
return tree;
}
test('parse - @abstract', function () {
expect(
evaluate(function () {
/** @abstract */
})[0].abstract
).toBe(true);
});
test('parse - @access', function () {
expect(
evaluate(function () {
/** @access public */
})[0].access
).toBe('public');
expect(
evaluate(function () {
/** @access protected */
})[0].access
).toBe('protected');
expect(
evaluate(function () {
/** @access private */
})[0].access
).toBe('private');
});
test('parse - @alias', function () {});
test('parse - @arg', function () {});
test('parse - @argument', function () {});
test('parse - @async', function () {
expect(
evaluate(function () {
/** @async */
})[0].async
).toBe(true);
});
test('parse - @augments', function () {
expect(
evaluate(function () {
/** @augments Foo */
})[0].augments[0].name
).toBe('Foo');
});
test('parse - @description', function () {
expect(
evaluate(function () {
/**
* This is a free-form description
* @description This tagged description wins, and [is markdown](http://markdown.com).
*/
})[0].description
).toEqual(
remarkParse(
'This tagged description wins, and [is markdown](http://markdown.com).'
)
);
});
/*
* Dossier-style augments tag
* https://github.com/google/closure-library/issues/746
*/
test('parse - @augments in dossier style', function () {
expect(
evaluate(function () {
/** @augments {Foo} */
})[0].augments[0].name
).toBe('Foo');
});
test('parse - @augments of complex passes through', function () {
expect(
evaluate(function () {
/** @augments {function()} */
})[0].augments
).toEqual([]);
});
test('parse - @author', function () {});
test('parse - @borrows', function () {});
test('parse - @callback', function () {
expect(
pick(
evaluate(function () {
/** @callback name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
name: 'name',
kind: 'typedef',
type: {
type: 'NameExpression',
name: 'Function'
}
});
});
test('parse - @class', function () {
expect(
pick(
evaluate(function () {
/** @class */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'class'
});
expect(
pick(
evaluate(function () {
/** @class name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
name: 'name',
kind: 'class'
});
expect(
pick(
evaluate(function () {
/** @class {Object} name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
name: 'name',
kind: 'class',
type: {
type: 'NameExpression',
name: 'Object'
}
});
});
test('parse - @classdesc', function () {
expect(
evaluate(function () {
/** @classdesc test */
})[0].classdesc
).toEqual(remarkParse('test'));
});
test('parse - @const', function () {});
test('parse - @constant', function () {
expect(
pick(
evaluate(function () {
/** @constant */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'constant'
});
expect(
pick(
evaluate(function () {
/** @constant name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'constant',
name: 'name'
});
expect(
pick(
evaluate(function () {
/** @constant {Object} */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'constant',
type: {
type: 'NameExpression',
name: 'Object'
}
});
expect(
pick(
evaluate(function () {
/** @constant {Object} name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'constant',
name: 'name',
type: {
type: 'NameExpression',
name: 'Object'
}
});
});
test('parse - @constructor', function () {});
test('parse - @constructs', function () {});
test('parse - @copyright', function () {
expect(
evaluate(function () {
/** @copyright test */
})[0].copyright
).toEqual(remarkParse('test'));
});
test('parse - @default', function () {});
test('parse - @defaultvalue', function () {});
test('parse - @deprecated', function () {
expect(
evaluate(function () {
/** @deprecated test */
})[0].deprecated
).toEqual(remarkParse('test'));
});
test('parse - @desc', function () {
expect(
evaluate(function () {
/** @desc test */
})[0].description
).toEqual(remarkParse('test'));
});
test('parse - @description', function () {
expect(
evaluate(function () {
/** @description test */
})[0].description
).toEqual(remarkParse('test'));
});
test('parse - description', function () {
expect(
evaluate(function () {
/** test */
})[0].description
).toEqual(remarkParse('test'));
});
test('parse - @emits', function () {});
test('parse - @enum', function () {
expect(
pick(
evaluate(function () {
/** @enum {string} */
})[0],
['kind', 'type']
)
).toEqual({
kind: 'enum',
type: {
type: 'NameExpression',
name: 'string'
}
});
});
test('parse - @event', function () {
expect(
pick(
evaluate(function () {
/** @event name */
})[0],
['kind', 'name']
)
).toEqual({
kind: 'event',
name: 'name'
});
});
test('parse - @example', function () {
expect(
evaluate(function () {
/** @example test */
})[0].examples[0]
).toEqual({
description: 'test'
});
expect(
evaluate(function () {
/**
* @example
* a
* b
*/
})[0].examples[0]
).toEqual({
description: 'a\nb'
});
expect(
evaluate(function () {
/**
* @example <caption>caption</caption>
* a
* b
*/
})[0].examples[0]
).toEqual({
description: 'a\nb',
caption: remarkParse('caption')
});
expect(
evaluate(function () {
/** @example */
})[0].errors[0]
).toEqual({
message: '@example without code',
commentLineNumber: 0
});
});
test('parse - @exception', function () {});
test('parse - @exports', function () {});
test('parse - @extends', function () {
expect(
evaluate(function () {
/** @extends Foo */
})[0].augments[0].name
).toEqual('Foo');
});
test('parse - @external', function () {
expect(
pick(
evaluate(function () {
/** @external name */
})[0],
['kind', 'name']
)
).toEqual({
kind: 'external',
name: 'name'
});
});
test('parse - @file', function () {
expect(
pick(
evaluate(function () {
/** @file */
})[0],
['kind']
)
).toEqual({
kind: 'file'
});
expect(
pick(
evaluate(function () {
/** @file desc */
})[0],
['kind', 'description']
)
).toEqual({
kind: 'file',
description: remarkParse('desc')
});
});
test('parse - @fileoverview', function () {});
test('parse - @fires', function () {});
test('parse - @func', function () {});
test('parse - @function', function () {
expect(
pick(
evaluate(function () {
/** @function */
})[0],
['kind', 'name']
)
).toEqual({
kind: 'function'
});
expect(
pick(
evaluate(function () {
/** @function name */
})[0],
['kind', 'name']
)
).toEqual({
kind: 'function',
name: 'name'
});
// When @function takes a name, it is acting as a shorthand for @name and
// should detach from code the same way @name does.
expect(
evaluate(function () {
/** @function */
function foo() {}
})[0].context.ast
).toBeDefined();
expect(
evaluate(function () {
/** @function name */
function foo() {}
})[0].context.ast
).toBeUndefined();
});
test('parse - @generator', function () {
expect(
evaluate(function () {
/** @generator */
})[0].generator
).toBe(true);
});
test('parse - @global', function () {
expect(
evaluate(function () {
/** @global */
})[0].scope
).toBe('global');
});
test('parse - @hideconstructor', function () {
expect(
evaluate(function () {
/** @hideconstructor */
})[0].hideconstructor
).toBe(true);
});
test('parse - @host', function () {});
test('parse - @ignore', function () {
expect(
evaluate(function () {
/** @ignore */
})[0].ignore
).toBe(true);
});
test('parse - @implements', function () {
expect(
evaluate(function () {
/** @implements {Foo} */
})[0].implements[0].name
).toEqual('Foo');
});
test('parse - @inheritdoc', function () {});
test('parse - @inner', function () {
expect(
evaluate(function () {
/** @inner*/
})[0].scope
).toBe('inner');
});
test('parse - @instance', function () {
expect(
evaluate(function () {
/** @instance*/
})[0].scope
).toBe('instance');
});
test('parse - @interface', function () {
expect(
evaluate(function () {
/** @interface */
})[0].kind
).toEqual('interface');
expect(
evaluate(function () {
/** @interface Foo */
})[0].name
).toEqual('Foo');
});
test('parse - @kind', function () {
expect(
evaluate(function () {
/** @kind class */
})[0].kind
).toBe('class');
});
test('parse - @license', function () {});
test('parse - @listens', function () {});
test('parse - @member', function () {
expect(
pick(
evaluate(function () {
/** @member */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'member'
});
expect(
pick(
evaluate(function () {
/** @member name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'member',
name: 'name'
});
expect(
pick(
evaluate(function () {
/** @member {Object} */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'member',
type: {
type: 'NameExpression',
name: 'Object'
}
});
expect(
pick(
evaluate(function () {
/** @member {Object} name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'member',
name: 'name',
type: {
type: 'NameExpression',
name: 'Object'
}
});
});
test('parse - @memberof', function () {
expect(
evaluate(function () {
/** @memberof test */
})[0].memberof
).toBe('test');
});
test('parse - @method', function () {});
test('parse - @mixes', function () {});
test('parse - @mixin', function () {
expect(
pick(
evaluate(function () {
/** @mixin */
})[0],
['kind', 'name']
)
).toEqual({
kind: 'mixin'
});
expect(
pick(
evaluate(function () {
/** @mixin name */
})[0],
['kind', 'name']
)
).toEqual({
kind: 'mixin',
name: 'name'
});
});
test('parse - @module', function () {
expect(
pick(
evaluate(function () {
/** @module */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'module'
});
expect(
pick(
evaluate(function () {
/** @module name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'module',
name: 'name'
});
expect(
pick(
evaluate(function () {
/** @module {Object} name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'module',
name: 'name',
type: {
type: 'NameExpression',
name: 'Object'
}
});
});
test('parse - @name', function () {
expect(
evaluate(function () {
/** @name test */
})[0].name
).toBe('test');
expect(
evaluate(function () {
/** @name foo */
const bar = 0;
})[0].context.ast
).toBeUndefined();
});
test('parse - @namespace', function () {
expect(
pick(
evaluate(function () {
/** @namespace */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'namespace'
});
expect(
pick(
evaluate(function () {
/** @namespace name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'namespace',
name: 'name'
});
expect(
pick(
evaluate(function () {
/** @namespace {Object} name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'namespace',
name: 'name',
type: {
type: 'NameExpression',
name: 'Object'
}
});
});
test('parse - @override', function () {
expect(
evaluate(function () {
/** @override */
})[0].override
).toBe(true);
});
test('parse - @overview', function () {});
test('parse - @param', function () {
expect(
evaluate(function () {
/** @param test */
})[0].params[0]
).toEqual({
name: 'test',
title: 'param',
lineNumber: 0
});
expect(
evaluate(function () {
/** @param {number} test */
})[0].params[0]
).toEqual({
name: 'test',
title: 'param',
type: {
name: 'number',
type: 'NameExpression'
},
lineNumber: 0
});
expect(
evaluate(function () {
/** @param {number} test - desc */
})[0].params[0]
).toEqual({
name: 'test',
title: 'param',
type: {
name: 'number',
type: 'NameExpression'
},
description: remarkParse('desc'),
lineNumber: 0
});
});
test('parse - @private', function () {
expect(
evaluate(function () {
/** @private */
})[0].access
).toBe('private');
});
test('parse - @prop', function () {
expect(
evaluate(function () {
/** @prop {number} test */
})[0].properties[0]
).toEqual({
name: 'test',
title: 'property',
type: {
name: 'number',
type: 'NameExpression'
},
lineNumber: 0
});
expect(
evaluate(function () {
/** @prop {number} test - desc */
})[0].properties[0]
).toEqual({
name: 'test',
title: 'property',
type: {
name: 'number',
type: 'NameExpression'
},
description: remarkParse('desc'),
lineNumber: 0
});
});
test('parse - @property', function () {
expect(
evaluate(function () {
/** @property {number} test */
})[0].properties[0]
).toEqual({
name: 'test',
title: 'property',
type: {
name: 'number',
type: 'NameExpression'
},
lineNumber: 0
});
expect(
evaluate(function () {
/** @property {number} test - desc */
})[0].properties[0]
).toEqual({
name: 'test',
title: 'property',
type: {
name: 'number',
type: 'NameExpression'
},
description: remarkParse('desc'),
lineNumber: 0
});
});
test('parse - @protected', function () {
expect(
evaluate(function () {
/** @protected */
})[0].access
).toBe('protected');
});
test('parse - @public', function () {});
test('parse - @readonly', function () {
expect(
evaluate(function () {
/** @readonly */
})[0].readonly
).toBe(true);
});
test('parse - @requires', function () {});
test('parse - @return', function () {
expect(
evaluate(function () {
/** @return test */
})[0].returns[0]
).toEqual({
title: 'returns',
description: remarkParse('test')
});
expect(
evaluate(function () {
/** @return {number} test */
})[0].returns[0]
).toEqual({
description: remarkParse('test'),
title: 'returns',
type: {
name: 'number',
type: 'NameExpression'
}
});
});
test('parse - @returns', function () {
expect(
evaluate(function () {
/** @returns test */
})[0].returns[0]
).toEqual({
title: 'returns',
description: remarkParse('test')
});
expect(
evaluate(function () {
/** @returns {number} test */
})[0].returns[0]
).toEqual({
description: remarkParse('test'),
title: 'returns',
type: {
name: 'number',
type: 'NameExpression'
}
});
});
test('parse - @see', function () {
expect(
evaluate(function () {
/** @see [test](#test) */
})[0].sees
).toEqual([
{
title: 'sees',
description: remarkParse('[test](#test)')
}
]);
expect(
evaluate(function () {
/**
* @see [a](#a)
* @see [b](#b)
*/
})[0].sees
).toEqual([
{
title: 'sees',
description: remarkParse('[a](#a)')
},
{
title: 'sees',
description: remarkParse('[b](#b)')
}
]);
});
test('parse - @since', function () {});
test('parse - @static', function () {
expect(
evaluate(function () {
/** @static */
})[0].scope
).toBe('static');
});
test('parse - @summary', function () {
expect(
evaluate(function () {
/** @summary test */
})[0].summary
).toEqual(remarkParse('test'));
});
test('parse - @this', function () {});
test('parse - @throws', function () {
expect(
evaluate(function () {
/** @throws desc */
})[0].throws[0]
).toEqual({
description: remarkParse('desc')
});
expect(
evaluate(function () {
/** @throws {Error} */
})[0].throws[0]
).toEqual({
type: {
name: 'Error',
type: 'NameExpression'
}
});
expect(
evaluate(function () {
/** @throws {Error} desc */
})[0].throws[0]
).toEqual({
type: {
name: 'Error',
type: 'NameExpression'
},
description: remarkParse('desc')
});
expect(
evaluate(function () {
/**
* @throws a
* @throws b
*/
})[0].throws
).toEqual([
{
description: remarkParse('a')
},
{
description: remarkParse('b')
}
]);
});
test('parse - @todo', function () {
expect(
evaluate(function () {
/** @todo test */
})[0].todos
).toEqual([remarkParse('test')]);
expect(
evaluate(function () {
/**
* @todo a
* @todo b
*/
})[0].todos
).toEqual([remarkParse('a'), remarkParse('b')]);
});
test('parse - @tutorial', function () {});
test('parse - @type', function () {});
test('parse - @typedef', function () {
expect(
pick(
evaluate(function () {
/** @typedef {Object} name */
})[0],
['kind', 'name', 'type']
)
).toEqual({
kind: 'typedef',
name: 'name',
type: {
type: 'NameExpression',
name: 'Object'
}
});
});
test('parse - @var', function () {});
test('parse - @variation', function () {
expect(
evaluate(function () {
/** @variation 1 */
})[0].variation
).toBe(1);
});
test('parse - @version', function () {});
test('parse - @virtual', function () {});
test('parse - @yield', function () {
expect(
evaluate(function () {
/** @yield test */
})[0].yields[0]
).toEqual({
title: 'yields',
description: remarkParse('test')
});
expect(
evaluate(function () {
/** @yield {number} test */
})[0].yields[0]
).toEqual({
description: remarkParse('test'),
title: 'yields',
type: {
name: 'number',
type: 'NameExpression'
}
});
});
test('parse - @yields', function () {
expect(
evaluate(function () {
/** @yields test */
})[0].yields[0]
).toEqual({
title: 'yields',
description: remarkParse('test')
});
expect(
evaluate(function () {
/** @yields {number} test */
})[0].yields[0]
).toEqual({
description: remarkParse('test'),
title: 'yields',
type: {
name: 'number',
type: 'NameExpression'
}
});
});
test('parse - unknown tag', function () {
expect(
evaluate(function () {
/** @unknown */
})[0].errors[0]
).toEqual({
message: 'unknown tag @unknown',
commentLineNumber: 0
});
});
test('parse - {@link}', function () {
expect(
evaluate(function () {
/** {@link Foo} */
})[0].description
).toEqual(addJSDocTag(remarkParse('[Foo](Foo)')));
expect(
evaluate(function () {
/** {@link Foo|text} */
})[0].description
).toEqual(addJSDocTag(remarkParse('[text](Foo)')));
expect(
evaluate(function () {
/** {@link Foo text} */
})[0].description
).toEqual(addJSDocTag(remarkParse('[text](Foo)')));
});
test('parse - {@linkcode}', function () {});
test('parse - {@linkplain}', function () {});
test('parse - {@tutorial}', function () {
expect(
evaluate(function () {
/** {@tutorial id} */
})[0].description
).toEqual({
type: 'root',
children: [
{
type: 'paragraph',
children: [
{
type: 'tutorial',
url: 'id',
jsdoc: true,
title: null,
children: [
{
type: 'text',
value: 'id'
}
]
}
]
}
]
});
expect(
evaluate(function () {
/** {@tutorial id|text} */
})[0].description
).toEqual({
type: 'root',
children: [
{
type: 'paragraph',
children: [
{
type: 'tutorial',
url: 'id',
jsdoc: true,
title: null,
children: [
{
type: 'text',
value: 'text'
}
]
}
]
}
]
});
expect(
evaluate(function () {
/** {@tutorial id text} */
})[0].description
).toEqual({
type: 'root',
children: [
{
type: 'paragraph',
children: [
{
type: 'tutorial',
url: 'id',
jsdoc: true,
title: null,
children: [
{
type: 'text',
value: 'text'
}
]
}
]
}
]
});
});