.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / lodash / fp / _baseConvert.js
1 var mapping = require('./_mapping'),
2     fallbackHolder = require('./placeholder');
3
4 /** Built-in value reference. */
5 var push = Array.prototype.push;
6
7 /**
8  * Creates a function, with an arity of `n`, that invokes `func` with the
9  * arguments it receives.
10  *
11  * @private
12  * @param {Function} func The function to wrap.
13  * @param {number} n The arity of the new function.
14  * @returns {Function} Returns the new function.
15  */
16 function baseArity(func, n) {
17   return n == 2
18     ? function(a, b) { return func.apply(undefined, arguments); }
19     : function(a) { return func.apply(undefined, arguments); };
20 }
21
22 /**
23  * Creates a function that invokes `func`, with up to `n` arguments, ignoring
24  * any additional arguments.
25  *
26  * @private
27  * @param {Function} func The function to cap arguments for.
28  * @param {number} n The arity cap.
29  * @returns {Function} Returns the new function.
30  */
31 function baseAry(func, n) {
32   return n == 2
33     ? function(a, b) { return func(a, b); }
34     : function(a) { return func(a); };
35 }
36
37 /**
38  * Creates a clone of `array`.
39  *
40  * @private
41  * @param {Array} array The array to clone.
42  * @returns {Array} Returns the cloned array.
43  */
44 function cloneArray(array) {
45   var length = array ? array.length : 0,
46       result = Array(length);
47
48   while (length--) {
49     result[length] = array[length];
50   }
51   return result;
52 }
53
54 /**
55  * Creates a function that clones a given object using the assignment `func`.
56  *
57  * @private
58  * @param {Function} func The assignment function.
59  * @returns {Function} Returns the new cloner function.
60  */
61 function createCloner(func) {
62   return function(object) {
63     return func({}, object);
64   };
65 }
66
67 /**
68  * A specialized version of `_.spread` which flattens the spread array into
69  * the arguments of the invoked `func`.
70  *
71  * @private
72  * @param {Function} func The function to spread arguments over.
73  * @param {number} start The start position of the spread.
74  * @returns {Function} Returns the new function.
75  */
76 function flatSpread(func, start) {
77   return function() {
78     var length = arguments.length,
79         lastIndex = length - 1,
80         args = Array(length);
81
82     while (length--) {
83       args[length] = arguments[length];
84     }
85     var array = args[start],
86         otherArgs = args.slice(0, start);
87
88     if (array) {
89       push.apply(otherArgs, array);
90     }
91     if (start != lastIndex) {
92       push.apply(otherArgs, args.slice(start + 1));
93     }
94     return func.apply(this, otherArgs);
95   };
96 }
97
98 /**
99  * Creates a function that wraps `func` and uses `cloner` to clone the first
100  * argument it receives.
101  *
102  * @private
103  * @param {Function} func The function to wrap.
104  * @param {Function} cloner The function to clone arguments.
105  * @returns {Function} Returns the new immutable function.
106  */
107 function wrapImmutable(func, cloner) {
108   return function() {
109     var length = arguments.length;
110     if (!length) {
111       return;
112     }
113     var args = Array(length);
114     while (length--) {
115       args[length] = arguments[length];
116     }
117     var result = args[0] = cloner.apply(undefined, args);
118     func.apply(undefined, args);
119     return result;
120   };
121 }
122
123 /**
124  * The base implementation of `convert` which accepts a `util` object of methods
125  * required to perform conversions.
126  *
127  * @param {Object} util The util object.
128  * @param {string} name The name of the function to convert.
129  * @param {Function} func The function to convert.
130  * @param {Object} [options] The options object.
131  * @param {boolean} [options.cap=true] Specify capping iteratee arguments.
132  * @param {boolean} [options.curry=true] Specify currying.
133  * @param {boolean} [options.fixed=true] Specify fixed arity.
134  * @param {boolean} [options.immutable=true] Specify immutable operations.
135  * @param {boolean} [options.rearg=true] Specify rearranging arguments.
136  * @returns {Function|Object} Returns the converted function or object.
137  */
138 function baseConvert(util, name, func, options) {
139   var isLib = typeof name == 'function',
140       isObj = name === Object(name);
141
142   if (isObj) {
143     options = func;
144     func = name;
145     name = undefined;
146   }
147   if (func == null) {
148     throw new TypeError;
149   }
150   options || (options = {});
151
152   var config = {
153     'cap': 'cap' in options ? options.cap : true,
154     'curry': 'curry' in options ? options.curry : true,
155     'fixed': 'fixed' in options ? options.fixed : true,
156     'immutable': 'immutable' in options ? options.immutable : true,
157     'rearg': 'rearg' in options ? options.rearg : true
158   };
159
160   var defaultHolder = isLib ? func : fallbackHolder,
161       forceCurry = ('curry' in options) && options.curry,
162       forceFixed = ('fixed' in options) && options.fixed,
163       forceRearg = ('rearg' in options) && options.rearg,
164       pristine = isLib ? func.runInContext() : undefined;
165
166   var helpers = isLib ? func : {
167     'ary': util.ary,
168     'assign': util.assign,
169     'clone': util.clone,
170     'curry': util.curry,
171     'forEach': util.forEach,
172     'isArray': util.isArray,
173     'isError': util.isError,
174     'isFunction': util.isFunction,
175     'isWeakMap': util.isWeakMap,
176     'iteratee': util.iteratee,
177     'keys': util.keys,
178     'rearg': util.rearg,
179     'toInteger': util.toInteger,
180     'toPath': util.toPath
181   };
182
183   var ary = helpers.ary,
184       assign = helpers.assign,
185       clone = helpers.clone,
186       curry = helpers.curry,
187       each = helpers.forEach,
188       isArray = helpers.isArray,
189       isError = helpers.isError,
190       isFunction = helpers.isFunction,
191       isWeakMap = helpers.isWeakMap,
192       keys = helpers.keys,
193       rearg = helpers.rearg,
194       toInteger = helpers.toInteger,
195       toPath = helpers.toPath;
196
197   var aryMethodKeys = keys(mapping.aryMethod);
198
199   var wrappers = {
200     'castArray': function(castArray) {
201       return function() {
202         var value = arguments[0];
203         return isArray(value)
204           ? castArray(cloneArray(value))
205           : castArray.apply(undefined, arguments);
206       };
207     },
208     'iteratee': function(iteratee) {
209       return function() {
210         var func = arguments[0],
211             arity = arguments[1],
212             result = iteratee(func, arity),
213             length = result.length;
214
215         if (config.cap && typeof arity == 'number') {
216           arity = arity > 2 ? (arity - 2) : 1;
217           return (length && length <= arity) ? result : baseAry(result, arity);
218         }
219         return result;
220       };
221     },
222     'mixin': function(mixin) {
223       return function(source) {
224         var func = this;
225         if (!isFunction(func)) {
226           return mixin(func, Object(source));
227         }
228         var pairs = [];
229         each(keys(source), function(key) {
230           if (isFunction(source[key])) {
231             pairs.push([key, func.prototype[key]]);
232           }
233         });
234
235         mixin(func, Object(source));
236
237         each(pairs, function(pair) {
238           var value = pair[1];
239           if (isFunction(value)) {
240             func.prototype[pair[0]] = value;
241           } else {
242             delete func.prototype[pair[0]];
243           }
244         });
245         return func;
246       };
247     },
248     'nthArg': function(nthArg) {
249       return function(n) {
250         var arity = n < 0 ? 1 : (toInteger(n) + 1);
251         return curry(nthArg(n), arity);
252       };
253     },
254     'rearg': function(rearg) {
255       return function(func, indexes) {
256         var arity = indexes ? indexes.length : 0;
257         return curry(rearg(func, indexes), arity);
258       };
259     },
260     'runInContext': function(runInContext) {
261       return function(context) {
262         return baseConvert(util, runInContext(context), options);
263       };
264     }
265   };
266
267   /*--------------------------------------------------------------------------*/
268
269   /**
270    * Casts `func` to a function with an arity capped iteratee if needed.
271    *
272    * @private
273    * @param {string} name The name of the function to inspect.
274    * @param {Function} func The function to inspect.
275    * @returns {Function} Returns the cast function.
276    */
277   function castCap(name, func) {
278     if (config.cap) {
279       var indexes = mapping.iterateeRearg[name];
280       if (indexes) {
281         return iterateeRearg(func, indexes);
282       }
283       var n = !isLib && mapping.iterateeAry[name];
284       if (n) {
285         return iterateeAry(func, n);
286       }
287     }
288     return func;
289   }
290
291   /**
292    * Casts `func` to a curried function if needed.
293    *
294    * @private
295    * @param {string} name The name of the function to inspect.
296    * @param {Function} func The function to inspect.
297    * @param {number} n The arity of `func`.
298    * @returns {Function} Returns the cast function.
299    */
300   function castCurry(name, func, n) {
301     return (forceCurry || (config.curry && n > 1))
302       ? curry(func, n)
303       : func;
304   }
305
306   /**
307    * Casts `func` to a fixed arity function if needed.
308    *
309    * @private
310    * @param {string} name The name of the function to inspect.
311    * @param {Function} func The function to inspect.
312    * @param {number} n The arity cap.
313    * @returns {Function} Returns the cast function.
314    */
315   function castFixed(name, func, n) {
316     if (config.fixed && (forceFixed || !mapping.skipFixed[name])) {
317       var data = mapping.methodSpread[name],
318           start = data && data.start;
319
320       return start  === undefined ? ary(func, n) : flatSpread(func, start);
321     }
322     return func;
323   }
324
325   /**
326    * Casts `func` to an rearged function if needed.
327    *
328    * @private
329    * @param {string} name The name of the function to inspect.
330    * @param {Function} func The function to inspect.
331    * @param {number} n The arity of `func`.
332    * @returns {Function} Returns the cast function.
333    */
334   function castRearg(name, func, n) {
335     return (config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name]))
336       ? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n])
337       : func;
338   }
339
340   /**
341    * Creates a clone of `object` by `path`.
342    *
343    * @private
344    * @param {Object} object The object to clone.
345    * @param {Array|string} path The path to clone by.
346    * @returns {Object} Returns the cloned object.
347    */
348   function cloneByPath(object, path) {
349     path = toPath(path);
350
351     var index = -1,
352         length = path.length,
353         lastIndex = length - 1,
354         result = clone(Object(object)),
355         nested = result;
356
357     while (nested != null && ++index < length) {
358       var key = path[index],
359           value = nested[key];
360
361       if (value != null &&
362           !(isFunction(value) || isError(value) || isWeakMap(value))) {
363         nested[key] = clone(index == lastIndex ? value : Object(value));
364       }
365       nested = nested[key];
366     }
367     return result;
368   }
369
370   /**
371    * Converts `lodash` to an immutable auto-curried iteratee-first data-last
372    * version with conversion `options` applied.
373    *
374    * @param {Object} [options] The options object. See `baseConvert` for more details.
375    * @returns {Function} Returns the converted `lodash`.
376    */
377   function convertLib(options) {
378     return _.runInContext.convert(options)(undefined);
379   }
380
381   /**
382    * Create a converter function for `func` of `name`.
383    *
384    * @param {string} name The name of the function to convert.
385    * @param {Function} func The function to convert.
386    * @returns {Function} Returns the new converter function.
387    */
388   function createConverter(name, func) {
389     var realName = mapping.aliasToReal[name] || name,
390         methodName = mapping.remap[realName] || realName,
391         oldOptions = options;
392
393     return function(options) {
394       var newUtil = isLib ? pristine : helpers,
395           newFunc = isLib ? pristine[methodName] : func,
396           newOptions = assign(assign({}, oldOptions), options);
397
398       return baseConvert(newUtil, realName, newFunc, newOptions);
399     };
400   }
401
402   /**
403    * Creates a function that wraps `func` to invoke its iteratee, with up to `n`
404    * arguments, ignoring any additional arguments.
405    *
406    * @private
407    * @param {Function} func The function to cap iteratee arguments for.
408    * @param {number} n The arity cap.
409    * @returns {Function} Returns the new function.
410    */
411   function iterateeAry(func, n) {
412     return overArg(func, function(func) {
413       return typeof func == 'function' ? baseAry(func, n) : func;
414     });
415   }
416
417   /**
418    * Creates a function that wraps `func` to invoke its iteratee with arguments
419    * arranged according to the specified `indexes` where the argument value at
420    * the first index is provided as the first argument, the argument value at
421    * the second index is provided as the second argument, and so on.
422    *
423    * @private
424    * @param {Function} func The function to rearrange iteratee arguments for.
425    * @param {number[]} indexes The arranged argument indexes.
426    * @returns {Function} Returns the new function.
427    */
428   function iterateeRearg(func, indexes) {
429     return overArg(func, function(func) {
430       var n = indexes.length;
431       return baseArity(rearg(baseAry(func, n), indexes), n);
432     });
433   }
434
435   /**
436    * Creates a function that invokes `func` with its first argument transformed.
437    *
438    * @private
439    * @param {Function} func The function to wrap.
440    * @param {Function} transform The argument transform.
441    * @returns {Function} Returns the new function.
442    */
443   function overArg(func, transform) {
444     return function() {
445       var length = arguments.length;
446       if (!length) {
447         return func();
448       }
449       var args = Array(length);
450       while (length--) {
451         args[length] = arguments[length];
452       }
453       var index = config.rearg ? 0 : (length - 1);
454       args[index] = transform(args[index]);
455       return func.apply(undefined, args);
456     };
457   }
458
459   /**
460    * Creates a function that wraps `func` and applys the conversions
461    * rules by `name`.
462    *
463    * @private
464    * @param {string} name The name of the function to wrap.
465    * @param {Function} func The function to wrap.
466    * @returns {Function} Returns the converted function.
467    */
468   function wrap(name, func, placeholder) {
469     var result,
470         realName = mapping.aliasToReal[name] || name,
471         wrapped = func,
472         wrapper = wrappers[realName];
473
474     if (wrapper) {
475       wrapped = wrapper(func);
476     }
477     else if (config.immutable) {
478       if (mapping.mutate.array[realName]) {
479         wrapped = wrapImmutable(func, cloneArray);
480       }
481       else if (mapping.mutate.object[realName]) {
482         wrapped = wrapImmutable(func, createCloner(func));
483       }
484       else if (mapping.mutate.set[realName]) {
485         wrapped = wrapImmutable(func, cloneByPath);
486       }
487     }
488     each(aryMethodKeys, function(aryKey) {
489       each(mapping.aryMethod[aryKey], function(otherName) {
490         if (realName == otherName) {
491           var data = mapping.methodSpread[realName],
492               afterRearg = data && data.afterRearg;
493
494           result = afterRearg
495             ? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey)
496             : castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey);
497
498           result = castCap(realName, result);
499           result = castCurry(realName, result, aryKey);
500           return false;
501         }
502       });
503       return !result;
504     });
505
506     result || (result = wrapped);
507     if (result == func) {
508       result = forceCurry ? curry(result, 1) : function() {
509         return func.apply(this, arguments);
510       };
511     }
512     result.convert = createConverter(realName, func);
513     result.placeholder = func.placeholder = placeholder;
514
515     return result;
516   }
517
518   /*--------------------------------------------------------------------------*/
519
520   if (!isObj) {
521     return wrap(name, func, defaultHolder);
522   }
523   var _ = func;
524
525   // Convert methods by ary cap.
526   var pairs = [];
527   each(aryMethodKeys, function(aryKey) {
528     each(mapping.aryMethod[aryKey], function(key) {
529       var func = _[mapping.remap[key] || key];
530       if (func) {
531         pairs.push([key, wrap(key, func, _)]);
532       }
533     });
534   });
535
536   // Convert remaining methods.
537   each(keys(_), function(key) {
538     var func = _[key];
539     if (typeof func == 'function') {
540       var length = pairs.length;
541       while (length--) {
542         if (pairs[length][0] == key) {
543           return;
544         }
545       }
546       func.convert = createConverter(key, func);
547       pairs.push([key, func]);
548     }
549   });
550
551   // Assign to `_` leaving `_.prototype` unchanged to allow chaining.
552   each(pairs, function(pair) {
553     _[pair[0]] = pair[1];
554   });
555
556   _.convert = convertLib;
557   _.placeholder = _;
558
559   // Assign aliases.
560   each(keys(_), function(key) {
561     each(mapping.realToAlias[key] || [], function(alias) {
562       _[alias] = _[key];
563     });
564   });
565
566   return _;
567 }
568
569 module.exports = baseConvert;