fp docs - Inject default values and cap args.

This commit is contained in:
Jeroen Engels
2016-02-09 13:07:42 +01:00
committed by John-David Dalton
parent 5062f22839
commit 39735df82f
4 changed files with 526 additions and 66 deletions

View File

@@ -1,5 +1,6 @@
var _ = require('lodash'),
j = require('jscodeshift'),
recast = require('recast'),
Entry = require('docdown/lib/entry');
var baseGetParams = Entry.prototype.getParams;
@@ -11,14 +12,25 @@ function getMultilineValue(string, tagName) {
result = _.result(RegExp(prelude + '([\\s\\S]*?)' + postlude, 'gm').exec(string), 1, '');
return _.trim(result.replace(RegExp('(?:^|\\n)[\\t ]*\\*[\\t ]' + (tagName == 'example' ? '?' : '*'), 'g'), '\n'));
}
// Function copied from docdown/lib/entry that is not exported.
function hasTag(string, tagName) {
tagName = tagName == '*' ? '\\w+' : _.escapeRegExp(tagName);
return RegExp('^ *\\*[\\t ]*@' + tagName + '\\b', 'm').test(string);
}
function isWrapped(entry) {
return !hasTag(entry, 'static');
}
/**
* Extracts the entry's `name` data.
* Extract the entry's `name` data.
* Sub-part of Entry.prototype.getCall() that fetches the name. Using `Entry.prototype.getCall()`
* makes a call to getParams(), which itself call getBaseName --> infinite recursion.
*
* @param {Object} entry Entry whose name to extract.
* @param {object} entry Entry whose name to extract.
* @returns {string} The entry's `name` data.
*/
function getBaseName(entry) {
@@ -33,32 +45,38 @@ function getBaseName(entry) {
}
/**
* Returns the new ary of a given function.
* Return the new ary of a given function.
*
* @param {Object} mapping Mapping object that defines the arity of all functions.
* @param {String} name Name of the function associated to the call/function definition.
* @param {object} mapping Mapping object that defines the arity of all functions.
* @param {String} name Name of the function associated to the call/function definition.
* @param {boolean} wrapped Flag indicating whether method is wrapped. Will decrement ary if true.
* @return {number} Ary of the function as an integer
*/
function getMethodAry(mapping, name) {
return _.find(mapping.caps, function(cap) {
function getMethodAry(mapping, name, wrapped) {
var ary = _.find(mapping.caps, function(cap) {
return _.includes(mapping.aryMethod[cap], name) && cap;
});
if (_.isNumber(ary) && wrapped) {
return ary - 1;
}
return ary;
}
/**
* Reorders `params` for a given function definition/call.
* Reorder `params` for a given function definition/call.
*
* @param {Object} mapping Mapping object that defines if and how the `params` will be reordered.
* @param {String} name Name of the function associated to the call/function definition.
* @param {*[]} params Parameters/arguments to reorder.
* @param {object} mapping Mapping object that defines if and how the `params` will be reordered.
* @param {String} name Name of the function associated to the call/function definition.
* @param {*[]} params Parameters/arguments to reorder.
* @param {boolean} wrapped Flag indicating whether method is wrapped. Will decrement ary if true.
* @returns {*[]} Reordered parameters/arguments.
*/
function reorderParams(mapping, name, params) {
function reorderParams(mapping, name, params, wrapped) {
// Check if reordering is needed.
if (!mapping || mapping.skipRearg[name]) {
return params;
}
var reargOrder = mapping.methodRearg[name] || mapping.aryRearg[getMethodAry(mapping, name)];
var reargOrder = mapping.methodRearg[name] || mapping.aryRearg[getMethodAry(mapping, name, wrapped)];
if (!reargOrder) {
return params;
}
@@ -72,28 +90,41 @@ function reorderParams(mapping, name, params) {
var dotsRegex = /^\.\.\./;
var parensRegex = /^\((.*)\)$/;
var squareBracketsRegex = /^\[(.*)\]$/;
var arrayRegex = /\[\]$/;
/**
* Return `types` as '(X|Y|...)' if `types` contains multiple values, `types[0]` otherwise.
*
* @param {string[]} types Possible types of the parameter.
* @return {string} `types` as a string.
*/
function wrapInParensIfMultiple(types) {
if (types.length > 1) {
return '(' + types.join('|') + ')';
}
return types;
return types[0];
}
function singleItemOrArrayOf(types) {
return types + '|' + types + '[]';
/**
* Transform parameter type from 'X' to 'X|X[]'.
*
* @param {string[]} param Array whose first item is a description of the parameter type.
* @return {string[]} `param` with the updated type.
*/
function singleItemOrArrayOf(type) {
return type + '|' + type + '[]';
}
/**
* Replace parameter type from something like `...number` to `number|number[]`.
*
* @param {string[]} param Array whose first item is a description of the parameter type.
* @param {string[]} param Array whose first item is a description of the parameter type.
* @return {string[]} `param` with the updated type.
*/
function removeDotsFromType(param) {
function removeDotsFromTypeAndAllowMultiple(param) {
var type = param[0];
if (!type.startsWith('...')) {
if (!dotsRegex.test(type)) {
return param;
}
@@ -112,15 +143,89 @@ function removeDotsFromType(param) {
return [newType].concat(_.tail(param));
}
function updateParamsDescription(mapping, entry, params) {
var paramsWithoutDots = params.map(removeDotsFromType);
return reorderParams(mapping, getBaseName(entry), paramsWithoutDots);
/**
* Replace parameter type from something like `...number` to `number|number[]`.
*
* @param {string[]} param Array whose first item is a description of the parameter type.
* @return {string[]} `param` with the updated type.
*/
function removeDotsFromType(param) {
var type = param[0];
if (!dotsRegex.test(type)) {
return param;
}
var newType = type
.replace(dotsRegex, '')
.replace(parensRegex, '$1');
return [newType].concat(_.tail(param));
}
/**
* Returns a function that extracts the entry's `param` data, reordered according to `mapping`.
* Find and duplicate the parameter with a type of the form '...x'.
*
* @param {Object} mapping Mapping object that defines if and how the `params` will be reordered.
* @param {string} name Name of the method.
* @param {string[]} params Description of the parameters of the method.
* @return {string[]} Updated parameters.
*/
function duplicateRestArrays(name, params) {
var indexOfRestParam = _.findIndex(params, function(param) {
return dotsRegex.test(param[0]);
});
if (indexOfRestParam === -1) {
console.log('WARNING: method `' + name + '`',
'is capped to more arguments than its declared number of parameters,',
'but does not have a parameter like `...x`');
}
// duplicates param[indexOfRestParam] at its position
return params.slice(0, indexOfRestParam + 1)
.concat(params.slice(indexOfRestParam));
}
/**
* Remove the optional default value and brackets around the name of the method.
*
* @param {string[]} param Array whose second item is the name of the param of the form
* 'name', '[name]' or [name=defaultValue].
* @return {string[]} `param` with the updated name.
*/
function removeDefaultValue(param) {
var paramName = param[1]
.replace(squareBracketsRegex, '$1')
.split('=')
[0];
return [param[0], paramName, param[2]];
}
function updateParamsDescription(mapping, entry, params) {
var tmpParams;
var name = getBaseName(entry);
var ary = getMethodAry(mapping, name);
var wrapped = isWrapped(entry);
if (wrapped) {
// Needs one less argument when wrapped
ary = ary - 1;
params.shift();
}
if (ary > params.length) {
tmpParams = duplicateRestArrays(name, params)
.map(removeDotsFromType);
} else {
tmpParams = params
.map(removeDotsFromTypeAndAllowMultiple);
}
tmpParams = tmpParams.map(removeDefaultValue);
return reorderParams(mapping, name, tmpParams, wrapped);
}
/**
* Return a function that extracts the entry's `param` data, reordered according to `mapping`.
*
* @param {object} mapping Mapping object that defines if and how the `params` will be reordered.
* @returns {Function} Function that returns the entry's `param` data.
*/
function getReorderedParams(mapping) {
@@ -135,25 +240,160 @@ function getReorderedParams(mapping) {
};
}
function getDefaultValue(paramDescription) {
var paramName = paramDescription[1];
if (paramName[0] !== '[') {
return null;
}
return paramName
.slice(1, paramName.length - 1)
.split('=')
[1] || null;
}
/**
* Return an AST node representation of `str`.
*
* @param {object} j JSCodeShift object.
* @param {string} str String to convert.
* @return {ASTObject} AST node.
*/
function stringToASTNode(j, str) {
return j(str).find(j.Expression).paths()[0].value;
}
/**
* Return the name of a parameter from its description.
* @param {string[]} paramDescription Parameter description.
* @return {string} name of the parameter.
*/
function paramName(paramDescription) {
var paramName = paramDescription[1];
if (paramName[0] !== '[') {
return paramName;
}
return paramName
.slice(1, paramName.length - 1)
.split('=')
[0];
}
/**
* Return a AST node representation of `object.property`.
* If `object.property` can be evaluated (ex: [].length --> 0), the node will be simplified.
* If `defaultValue` references another argument, it will be replaced by the value of that argument.
*
* @param {object} j JSCodeShift object.
* @param {ASTObject} object Object of the member expression.
* @param {string} property Property of the member expression.
* @return {ASTObject} AST node.
*/
function memberExpressiontoASTNode(j, object, property) {
var node = j.memberExpression(object, j.identifier(property));
try {
// Attempt to evaluate the value of the node to have simpler calls
// [1, 2, 3, 4].length --> 4
var evaluatedNode = eval(recast.print(node).code);
return stringToASTNode(j, JSON.stringify(evaluatedNode));
} catch (e) {
return node;
}
}
/**
* Return a AST node representation of `defaultValue`.
* If `defaultValue` references another argument, it will be replaced by the value of that argument.
*
* @param {object} j JSCodeShift object.
* @param {string} defaultValue Value to convert.
* @param {ASTObject[]} args Arguments given to the function.
* @param {string[]} paramNames Name of the expected parameters.
* @return {ASTObject} AST node representation of `defaultValue`.
*/
function defaultValueToASTNode(j, defaultValue, args, paramNames) {
// var endValue = replaceValueByArgValue(j, defaultValue, args, paramNames);
var splitDefaultValue = defaultValue.split('.');
var indexOfReferencedParam = paramNames.indexOf(splitDefaultValue[0]);
if (indexOfReferencedParam !== -1) {
if (splitDefaultValue.length > 1) {
// defaultValue is probably of the type 'someArg.length'
// Other more complicated cases could be handled but none exist as of this writing.
return memberExpressiontoASTNode(j, args[indexOfReferencedParam], splitDefaultValue[1]);
}
return args[indexOfReferencedParam];
}
return stringToASTNode(j, defaultValue);
}
function mapRight(array, fn) {
var res = [];
var index = array.length;
while (index--) {
res = [fn(array[index], index)].concat(res);
}
return res;
}
/**
* Return the list of arguments, augmented by the default value of the arguments that were ommitted.
* The augmentation only happens when the method call is made without some of the optional arguments,
* and when the arguments these optional arguments have become compulsory.
* For a `function fn(a, b, c=0, d=b.length) { ... }` with an arity of 4,
* when called with `args` [a, ['b']], returns [a, ['b'], 0, ['b'].length].
* If possible, the value will be evaluated such that ̀`['b'].length` becomes `1`.
*
* @param {object} j JSCodeShift object.
* @param {object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {String} name Name of the function associated to the call/function definition.
* @param {ASTObject[]} args Arguments to concatenate.
* @param {string[][]} paramsDescription Description of the expected params.
* @return {ASTObject[]} Args along with missing arguments.
*/
function addMissingArguments(j, mapping, name, args, paramsDescription) {
var ary = getMethodAry(mapping, name);
if (ary === undefined) {
console.log('WARNING: method `' + name + '` is not capped');
}
ary = ary || 1;
if (ary <= args.length) {
return args;
}
var paramNames = paramsDescription.map(paramName);
var tmpArgs = _.clone(args);
var newArgs = mapRight(_.take(paramsDescription, ary), function(paramDescription, index) {
if (index === tmpArgs.length - 1) {
return tmpArgs.pop();
}
var defaultValue = getDefaultValue(paramDescription);
if (defaultValue !== null) {
return defaultValueToASTNode(j, defaultValue, args, paramNames);
}
return tmpArgs.pop();
});
return newArgs;
}
/**
* Concatenate arguments into an array of arguments.
* For a `function fn(a, b, ...args) { ... }` with an arity of 3,
* when called with `args` [a, b, c, d, e, f], returns [a, b, [c, d, e, f]].
*
* @param {object} j JSCodeShift object.
* @param {Object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {String} name Name of the function associated to the call/function definition.
* @param {ASTobjects[]} Arguments to concatenate.
* @return {ASTobjects[]} Concatenated arguments
* @param {ASTObject[]} args Arguments to concatenate.
* @return {ASTObject[]} Concatenated arguments
*/
function concatExtraArgs(j, mapping, name, args) {
var ary = getMethodAry(mapping, name);
if (ary === args.length) {
if (args.length <= ary) {
return args;
}
return _.take(args, ary - 1).concat(
j.arrayExpression(_.takeRight(args, args.length - ary + 1))
);
var concatenatedArgs = j.arrayExpression(_.takeRight(args, args.length - ary + 1));
return _.take(args, ary - 1).concat(concatenatedArgs);
}
/**
@@ -162,15 +402,16 @@ function concatExtraArgs(j, mapping, name, args) {
*
* @param {object} j JSCodeShift object.
* @param {ASTObject} root AST representation of the example
* @param {Object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {object} mapping Mapping object that defines if and how the arguments will be reordered.
* @return {ASTObject} AST object where the arguments are reordered/merged
*/
function reorderMethodArgs(j, root, mapping) {
function reorderMethodArgs(j, root, mapping, paramsDescription) {
root.find(j.CallExpression, { callee: { object: {name: '_' }}})
.replaceWith(function(callExpr, i) {
var value = callExpr.value;
var name = value.callee.property.name;
var args = concatExtraArgs(j, mapping, name, value.arguments);
var argsIncludingMissingOnes = addMissingArguments(j, mapping, name, value.arguments, paramsDescription)
var args = concatExtraArgs(j, mapping, name, argsIncludingMissingOnes);
return j.callExpression(
value.callee,
reorderParams(mapping, name, args)
@@ -190,21 +431,36 @@ function removeConsoleLogs(codeSample) {
/**
* Updates a code sample so that the arguments in the call are reordered according to `mapping`.
*
* @param {Object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {object} mapping Mapping object that defines if and how the arguments will be reordered.
* @param {string} codeSample Code sample to update.
* @returns {string} Updated code sample.
*/
function reorderParamsInExample(mapping, codeSample) {
function reorderParamsInExample(mapping, codeSample, paramsDescription) {
var root = j(removeConsoleLogs(codeSample));
reorderMethodArgs(j, root, mapping);
try {
reorderMethodArgs(j, root, mapping, paramsDescription);
} catch (error) {
console.error(codeSample);
console.error(error.stack);
process.exit(1);
}
return root.toSource();
}
function getOriginalParams() {
var prev = this._params;
this._params = undefined;
baseGetParams.call(this);
var result = this._params;
this._params = prev;
return result;
}
/**
* Returns a function that extracts the entry's `example` data,
* where function call arguments are reordered according to `mapping`.
*
* @param {Object} mapping Mapping object that defines if and how the `params` will be reordered.
* @param {object} mapping Mapping object that defines if and how the `params` will be reordered.
* @returns {Function} Function that returns the entry's `example` data.
*/
function getReorderedExample(mapping) {
@@ -213,7 +469,9 @@ function getReorderedExample(mapping) {
if (!result) {
return result;
}
var resultReordered = reorderParamsInExample(mapping, result);
var paramsDescription = getOriginalParams.call(this);
var resultReordered = reorderParamsInExample(mapping, result, paramsDescription);
return '```' + this.lang + '\n' + resultReordered + '\n```';
};
}

View File

@@ -5,11 +5,12 @@ var Entry = require('docdown/lib/entry');
var applyFPMapping = require('./apply-fp-mapping');
var mapping = require('../../fp/_mapping');
function toExample(name, lines) {
function toSource(name, paramLines, exampleLines, attachedToPrototype) {
var start = [
"/**",
" * ",
" * @example"
" * Foo",
" * "
];
var end = [
" */",
@@ -17,16 +18,23 @@ function toExample(name, lines) {
"",
"}"
];
var example = lines.map(function(line) {
var staticLine = attachedToPrototype ? [] : [' * @static'];
var params = paramLines.map(function(line) {
return ' * @param ' + line;
});
var example = (exampleLines || []).map(function(line) {
return ' * ' + line;
});
return [].concat(start, example, end).join('\n');
return [].concat(start, staticLine, params, [' * @example'], example, end).join('\n');
}
function toParams(name, lines) {
function toParams(name, lines, wrapped) {
var start = [
"/**",
" * ",
" * Foo",
" * "
];
var end = [
" * @returns Foo bar",
@@ -35,12 +43,32 @@ function toParams(name, lines) {
"",
"}"
];
var example = lines.map(function(line) {
var staticLine = wrapped ? [] : [' * @static'];
var params = lines.map(function(line) {
return ' * @param ' + line;
});
return [].concat(start, example, end).join('\n');
return [].concat(start, staticLine, params, end).join('\n');
}
var differenceBySource = toSource('differenceBy', [
'{Array} array The array to inspect.',
'{...Array} [values] The values to exclude.',
'{Function|Object|string} [iteratee=_.identity] The iteratee invoked per element.'
], [
"_.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);",
"// → [3.1, 1.3]",
"",
"// The `_.property` iteratee shorthand.",
"_.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');",
"// → [{ 'x': 2 }]"
]);
var setParams = [
'{Object} object The object to modify.',
'{Array|string} path The path of the property to set.',
'{*} value The value to set.'
];
describe('Docs FP mapping', function() {
var oldgetParams;
var oldgetExample;
@@ -48,6 +76,7 @@ describe('Docs FP mapping', function() {
before(function() {
oldgetParams = Entry.prototype.getParams;
oldgetExample = Entry.prototype.getExample;
mapping.aryMethod[2].push('customFun');
applyFPMapping(mapping);
});
@@ -58,15 +87,7 @@ describe('Docs FP mapping', function() {
describe('getExample', function() {
it('should reorder parameters', function() {
var example = toExample('differenceBy', [
"_.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor);",
"// → [3.1, 1.3]",
"",
"// The `_.property` iteratee shorthand.",
"_.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');",
"// → [{ 'x': 2 }]"
]);
var entry = new Entry(example, example);
var entry = new Entry(differenceBySource, differenceBySource);
var actual = entry.getExample();
@@ -83,7 +104,7 @@ describe('Docs FP mapping', function() {
});
it('should reorder parameters that have a special order', function() {
var example = toExample('set', [
var example = toSource('set', setParams, [
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"_.set(object, 'a[0].b.c', 4);",
"_.set(object, 'x[0].y.z', 5);",
@@ -102,7 +123,7 @@ describe('Docs FP mapping', function() {
});
it('should preserve comments', function() {
var example = toExample('set', [
var example = toSource('set', setParams, [
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"_.set(object, 'a[0].b.c', 4);",
"// => 4",
@@ -123,7 +144,7 @@ describe('Docs FP mapping', function() {
});
it('should remove console.logs from example', function() {
var example = toExample('set', [
var example = toSource('set', setParams, [
"var object = { 'a': [{ 'b': { 'c': 3 } }] };",
"",
"_.set(object, 'a[0].b.c', 4);",
@@ -152,7 +173,11 @@ describe('Docs FP mapping', function() {
});
it('should merge extra arguments into an array', function() {
var example = toExample('pullAt', [
var example = toSource('pullAt', [
'{Array} array The array to modify.',
'{...(number|number[])} [indexes] The indexes of elements to remove,\n' +
' * specified individually or in arrays.'
], [
"var array = [5, 10, 15, 20];",
"var evens = _.pullAt(array, 1, 3);",
"",
@@ -177,10 +202,139 @@ describe('Docs FP mapping', function() {
"```"
].join('\n'));
});
it('should inject default values into optional arguments that became compulsory', function() {
var example = toSource('sampleSize', [
'{Array|Object} collection The collection to sample.',
'{number} [n=0] The number of elements to sample.'
], [
"_.sampleSize([1, 2, 3]);",
"// => [3, 1]",
"",
"_.sampleSize([1, 2, 3], 4);",
"// => [2, 3, 1]"
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
"```js",
"_.sampleSize(0, [1, 2, 3]);",
"// => [3, 1]",
"",
"_.sampleSize(4, [1, 2, 3]);",
"// => [2, 3, 1]",
"```"
].join('\n'));
});
it('should inject referenced values into optional arguments that became compulsory, '
+ 'if a parameter\'s default value references parameter (direct reference)',
function() {
var example = toSource('customFun', [
'{Array} array Array',
'{number} [foo=array] Foo'
], [
"_.customFun([1, 2, 3]);",
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
"```js",
"_.customFun([1, 2, 3], [1, 2, 3]);",
"```"
].join('\n'));
});
it('should inject referenced values into optional arguments that became compulsory, '
+ 'if a parameter\'s default value references parameter (member expression)',
function() {
var example = toSource('fill', [
'{Array} array The array to fill.',
'{*} value The value to fill `array` with.',
'{number} [start=0] The start position.',
'{number} [end=array.length] The end position.'
], [
"var array = [1, 2, 3];",
"",
"_.fill(array, 'a');",
"console.log(array);",
"// => ['a', 'a', 'a']",
"",
"_.fill(Array(3), 2, 1);",
"// => [undefined, 2, 2]",
"",
"_.fill([4, 6, 8, 10], '*');",
"// => [*, '*', '*', *]"
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
"```js",
"var array = [1, 2, 3];",
"",
"_.fill(0, array.length, 'a', array);",
"// => ['a', 'a', 'a']",
"",
"_.fill(1, 3, 2, Array(3));",
"// => [undefined, 2, 2]",
"",
"_.fill(0, 4, '*', [4, 6, 8, 10]);",
"// => [*, '*', '*', *]",
"```"
].join('\n'));
});
it('should inject default values in the middle of the arguments', function() {
var example = toSource('inRange', [
'{number} number The number to check.',
'{number} [start=0] The start of the range.',
'{number} end The end of the range.'
], [
"_.inRange(4, 8);",
"// => true"
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
"```js",
"_.inRange(8, 0, 4);",
"// => true",
"```"
].join('\n'));
});
it('should not use ignored params as default values', function() {
var example = toSource('drop', [
'{Array} array The array to query.',
'{number} [n=1] The number of elements to drop.',
'{Object} [guard] Enables use as an iteratee for functions like `_.map`.'
], [
"_.drop([1, 2, 3]);",
"// => [2, 3]"
]);
var entry = new Entry(example, example);
var actual = entry.getExample();
assert.equal(actual, [
"```js",
"_.drop(1, [1, 2, 3]);",
"// => [2, 3]",
"```"
].join('\n'));
});
});
describe('getParams', function() {
it('should reorder arguments', function() {
it('should reorder arguments and remove default values', function() {
var example = toParams('differenceBy', [
'{Array} array The array to inspect.',
'{...Array} [values] The values to exclude.',
@@ -191,8 +345,8 @@ describe('Docs FP mapping', function() {
var actual = entry.getParams();
assert.deepEqual(actual, [
['Function|Object|string', '[iteratee=_.identity]', 'The iteratee invoked per element. '],
['Array|Array[]', '[values]', 'The values to exclude. '],
['Function|Object|string', 'iteratee', 'The iteratee invoked per element. '],
['Array|Array[]', 'values', 'The values to exclude. '],
['Array', 'array', 'The array to inspect. ']
]);
});
@@ -228,10 +382,57 @@ describe('Docs FP mapping', function() {
// TODO Remove this line in favor of the commented one.
// Is linked to a docdown (https://github.com/jdalton/docdown/pull/37)
// that does not handle parens in the arguments well
['((number|number)|((number|number)[]', '[indexes]', 'The indexes of elements to remove, specified individually or in arrays. '],
['((number|number)|((number|number)[]', 'indexes', 'The indexes of elements to remove, specified individually or in arrays. '],
// ['number|number[]', '[indexes]', 'The indexes of elements to remove, specified individually or in arrays. '],
['Array', 'array', 'The array to modify. '],
]);
});
});
it('should duplicate and de-restify "rest" parameters if there are less parameters than cap', function() {
var example = toParams('intersectionWith', [
'{...Array} [arrays] The arrays to inspect.',
'{Function} [comparator] The comparator invoked per element.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['Function', 'comparator', 'The comparator invoked per element. '],
['Array', 'arrays', 'The arrays to inspect. '],
['Array', 'arrays', 'The arrays to inspect. ']
]);
});
it('should consider method to have an ary of `ary - 1` when capped and wrapped', function() {
var wrapped = true;
var example = toParams('flatMap', [
'{Array} array The array to iterate over.',
'{Function|Object|string} [iteratee=_.identity] The function invoked per iteration.'
], wrapped);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['Function|Object|string', 'iteratee', 'The function invoked per iteration. ']
]);
});
it('should remove arguments ignored because of capping', function() {
var example = toParams('includes', [
'{Array|Object|string} collection The collection to search.',
'{*} value The value to search for.',
'{number} [fromIndex=0] The index to search from.'
]);
var entry = new Entry(example, example);
var actual = entry.getParams();
assert.deepEqual(actual, [
['*', 'value', 'The value to search for. '],
['Array|Object|string', 'collection', 'The collection to search. ']
]);
});
});

View File

@@ -12364,7 +12364,7 @@
* @memberOf _
* @category String
* @param {string} string The string to convert.
* @param {number} [radix] The radix to interpret `value` by.
* @param {number} [radix=10] The radix to interpret `value` by.
* @param- {Object} [guard] Enables use as an iteratee for functions like `_.map`.
* @returns {number} Returns the converted integer.
* @example
@@ -12910,7 +12910,7 @@
* @memberOf _
* @category String
* @param {string} [string=''] The string to truncate.
* @param {Object} [options] The options object.
* @param {Object} [options=({})] The options object.
* @param {number} [options.length=30] The maximum string length.
* @param {string} [options.omission='...'] The string to indicate text is omitted.
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
@@ -13829,7 +13829,7 @@
* @static
* @memberOf _
* @category Util
* @param {string} [prefix] The value to prefix the ID with.
* @param {string} [prefix=''] The value to prefix the ID with.
* @returns {string} Returns the unique ID.
* @example
*

View File

@@ -23,6 +23,7 @@
"platform": "^1.3.1",
"qunit-extras": "^1.4.5",
"qunitjs": "~1.21.0",
"recast": "^0.11.0",
"request": "^2.69.0",
"requirejs": "^2.1.22",
"sauce-tunnel": "^2.4.0",