annotate-esprima/scripts/lib/esprima-master/assets/orion/contentassist/doctrine.js
2014-04-15 11:04:48 +02:00

1484 lines
53 KiB
JavaScript
Executable file

/*
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*jslint bitwise:true plusplus:true */
/*global doctrine:true, exports:true, parseTypeExpression:true, parseTop:true*/
(function (exports) {
'use strict';
var VERSION,
Regex,
CanAccessStringByIndex,
typed,
jsdoc,
isArray;
// Sync with package.json.
VERSION = '0.0.4-dev';
// See also tools/generate-unicode-regex.py.
Regex = {
NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
};
CanAccessStringByIndex = typeof 'doctrine'[0] !== undefined;
function sliceSource(source, index, last) {
return source.slice(index, last);
}
isArray = Array.isArray;
if (!isArray) {
isArray = function isArray(ary) {
return Object.prototype.toString.call(ary) === '[object Array]';
};
}
if (!CanAccessStringByIndex) {
sliceSource = function sliceSource(source, index, last) {
return source.slice(index, last).join('');
};
}
function shallowCopy(obj) {
var ret = {}, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = obj[key];
}
}
return ret;
}
function isLineTerminator(ch) {
return ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029';
}
function isWhiteSpace(ch) {
return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
(ch === '\u000C') || (ch === '\u00A0') ||
(ch.charCodeAt(0) >= 0x1680 &&
'\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
}
function isDecimalDigit(ch) {
return '0123456789'.indexOf(ch) >= 0;
}
function isHexDigit(ch) {
return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
}
function isOctalDigit(ch) {
return '01234567'.indexOf(ch) >= 0;
}
function isASCIIAlphanumeric(ch) {
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9');
}
function isIdentifierStart(ch) {
return (ch === '$') || (ch === '_') || (ch === '\\') ||
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
}
function isIdentifierPart(ch) {
return (ch === '$') || (ch === '_') || (ch === '\\') ||
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
((ch >= '0') && (ch <= '9')) ||
((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
}
function isTypeName(ch) {
return '><(){}[],:*|?!='.indexOf(ch) === -1 && !isWhiteSpace(ch) && !isLineTerminator(ch);
}
function assert(cond, text) { }
if (VERSION.slice(-3) === 'dev') {
assert = function assert(cond, text) {
if (!cond) {
throw new Error(text);
}
};
}
function trim(str) {
return str.replace(/^\s+/, '').replace(/\s+$/, '');
}
function unwrapComment(doc) {
// JSDoc comment is following form
// /**
// * .......
// */
// remove /**, */ and *
var BEFORE_STAR = 0,
STAR = 1,
AFTER_STAR = 2,
index,
len,
mode,
result,
ch;
doc = doc.replace(/^\/\*\*/, '').replace(/\*\/$/, '');
index = 0;
len = doc.length;
mode = BEFORE_STAR;
result = '';
while (index < len) {
ch = doc[index];
switch (mode) {
case BEFORE_STAR:
if (isLineTerminator(ch)) {
result += ch;
} else if (ch === '*') {
mode = STAR;
} else if (!isWhiteSpace(ch)) {
result += ch;
mode = AFTER_STAR;
}
break;
case STAR:
if (!isWhiteSpace(ch)) {
result += ch;
}
mode = AFTER_STAR;
break;
case AFTER_STAR:
result += ch;
if (isLineTerminator(ch)) {
mode = BEFORE_STAR;
}
break;
}
index += 1;
}
return result;
}
// Type Expression Parser
(function (exports) {
var Syntax,
Token,
index,
previous,
source,
length,
token,
value;
Syntax = {
NullableLiteral: 'NullableLiteral',
AllLiteral: 'AllLiteral',
NullLiteral: 'NullLiteral',
UndefinedLiteral: 'UndefinedLiteral',
VoidLiteral: 'VoidLiteral',
UnionType: 'UnionType',
ArrayType: 'ArrayType',
RecordType: 'RecordType',
FieldType: 'FieldType',
FunctionType: 'FunctionType',
ParameterType: 'ParameterType',
RestType: 'RestType',
NonNullableType: 'NonNullableType',
OptionalType: 'OptionalType',
NullableType: 'NullableType',
NameExpression: 'NameExpression',
TypeApplication: 'TypeApplication'
};
Token = {
ILLEGAL: 0, // ILLEGAL
DOT: 1, // .
DOT_LT: 2, // .<
REST: 3, // ...
LT: 4, // <
GT: 5, // >
LPAREN: 6, // (
RPAREN: 7, // )
LBRACE: 8, // {
RBRACE: 9, // }
LBRACK: 10, // [
RBRACK: 11, // ]
COMMA: 12, // ,
COLON: 13, // :
STAR: 14, // *
PIPE: 15, // |
QUESTION: 16, // ?
BANG: 17, // !
EQUAL: 18, // =
NAME: 19, // name token
STRING: 20, // string
NUMBER: 21, // number
EOF: 22
};
function advance() {
var ch = source[index];
index += 1;
return ch;
}
function scanHexEscape(prefix) {
var i, len, ch, code = 0;
len = (prefix === 'u') ? 4 : 2;
for (i = 0; i < len; ++i) {
if (index < length && isHexDigit(source[index])) {
ch = advance();
code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
} else {
return '';
}
}
return String.fromCharCode(code);
}
function scanString() {
var str = '', quote, ch, code, unescaped, restore, octal = false;
quote = source[index];
++index;
while (index < length) {
ch = advance();
if (ch === quote) {
quote = '';
break;
} else if (ch === '\\') {
ch = advance();
if (!isLineTerminator(ch)) {
switch (ch) {
case 'n':
str += '\n';
break;
case 'r':
str += '\r';
break;
case 't':
str += '\t';
break;
case 'u':
case 'x':
restore = index;
unescaped = scanHexEscape(ch);
if (unescaped) {
str += unescaped;
} else {
index = restore;
str += ch;
}
break;
case 'b':
str += '\b';
break;
case 'f':
str += '\f';
break;
case 'v':
str += '\v';
break;
default:
if (isOctalDigit(ch)) {
code = '01234567'.indexOf(ch);
// \0 is not octal escape sequence
if (code !== 0) {
octal = true;
}
if (index < length && isOctalDigit(source[index])) {
octal = true;
code = code * 8 + '01234567'.indexOf(advance());
// 3 digits are only allowed when string starts
// with 0, 1, 2, 3
if ('0123'.indexOf(ch) >= 0 &&
index < length &&
isOctalDigit(source[index])) {
code = code * 8 + '01234567'.indexOf(advance());
}
}
str += String.fromCharCode(code);
} else {
str += ch;
}
break;
}
} else {
if (ch === '\r' && source[index] === '\n') {
++index;
}
}
} else if (isLineTerminator(ch)) {
break;
} else {
str += ch;
}
}
if (quote !== '') {
throw 'unexpected quote';
}
value = str;
return Token.STRING;
}
function scanNumber() {
var number, ch;
number = '';
if (ch !== '.') {
number = advance();
ch = source[index];
if (number === '0') {
if (ch === 'x' || ch === 'X') {
number += advance();
while (index < length) {
ch = source[index];
if (!isHexDigit(ch)) {
break;
}
number += advance();
}
if (number.length <= 2) {
// only 0x
throw 'unexpected token';
}
if (index < length) {
ch = source[index];
if (isIdentifierStart(ch)) {
throw 'unexpected token';
}
}
value = parseInt(number, 16);
return Token.NUMBER;
}
if (isOctalDigit(ch)) {
number += advance();
while (index < length) {
ch = source[index];
if (!isOctalDigit(ch)) {
break;
}
number += advance();
}
if (index < length) {
ch = source[index];
if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
throw 'unexpected token';
}
}
value = parseInt(number, 8);
return Token.NUMBER;
}
if (isDecimalDigit(ch)) {
throw 'unexpected token';
}
}
while (index < length) {
ch = source[index];
if (!isDecimalDigit(ch)) {
break;
}
number += advance();
}
}
if (ch === '.') {
number += advance();
while (index < length) {
ch = source[index];
if (!isDecimalDigit(ch)) {
break;
}
number += advance();
}
}
if (ch === 'e' || ch === 'E') {
number += advance();
ch = source[index];
if (ch === '+' || ch === '-') {
number += advance();
}
ch = source[index];
if (isDecimalDigit(ch)) {
number += advance();
while (index < length) {
ch = source[index];
if (!isDecimalDigit(ch)) {
break;
}
number += advance();
}
} else {
throw 'unexpected token';
}
}
if (index < length) {
ch = source[index];
if (isIdentifierStart(ch)) {
throw 'unexpected token';
}
}
value = parseFloat(number);
return Token.NUMBER;
}
function scanTypeName() {
var ch, ch2;
value = advance();
while (index < length && isTypeName(source[index])) {
ch = source[index];
if (ch === '.') {
if ((index + 1) < length) {
ch2 = source[index + 1];
if (ch2 === '<') {
break;
}
}
}
value += advance();
}
return Token.NAME;
}
function next() {
var ch;
previous = index;
while (index < length && isWhiteSpace(source[index])) {
advance();
}
if (index >= length) {
token = Token.EOF;
return token;
}
ch = source[index];
switch (ch) {
case '"':
token = scanString();
return token;
case ':':
advance();
token = Token.COLON;
return token;
case ',':
advance();
token = Token.COMMA;
return token;
case '(':
advance();
token = Token.LPAREN;
return token;
case ')':
advance();
token = Token.RPAREN;
return token;
case '[':
advance();
token = Token.LBRACK;
return token;
case ']':
advance();
token = Token.RBRACK;
return token;
case '{':
advance();
token = Token.LBRACE;
return token;
case '}':
advance();
token = Token.RBRACE;
return token;
case '.':
advance();
if (index < length) {
ch = source[index];
if (ch === '<') {
advance();
token = Token.DOT_LT;
return token;
}
if (ch === '.' && index + 1 < length && source[index + 1] === '.') {
advance();
advance();
token = Token.REST;
return token;
}
if (isDecimalDigit(ch)) {
token = scanNumber();
return token;
}
}
token = Token.DOT;
return token;
case '<':
advance();
token = Token.LT;
return token;
case '>':
advance();
token = Token.GT;
return token;
case '*':
advance();
token = Token.STAR;
return token;
case '|':
advance();
token = Token.PIPE;
return token;
case '?':
advance();
token = Token.QUESTION;
return token;
case '!':
advance();
token = Token.BANG;
return token;
case '=':
advance();
token = Token.EQUAL;
return token;
default:
if (isDecimalDigit(ch)) {
token = scanNumber();
return token;
}
// type string permits following case,
//
// namespace.module.MyClass
//
// this reduced 1 token TK_NAME
if (isTypeName(ch)) {
token = scanTypeName();
return token;
}
token = Token.ILLEGAL;
return token;
}
}
function consume(target, text) {
assert(token === target, text || 'consumed token not matched');
next();
}
function expect(target) {
if (token !== target) {
throw 'unexpected token';
}
next();
}
// UnionType := '(' TypeUnionList ')'
//
// TypeUnionList :=
// <<empty>>
// | NonemptyTypeUnionList
//
// NonemptyTypeUnionList :=
// TypeExpression
// | TypeExpression '|' NonemptyTypeUnionList
function parseUnionType() {
var elements;
consume(Token.LPAREN, 'UnionType should start with (');
elements = [];
if (token !== Token.RPAREN) {
while (true) {
elements.push(parseTypeExpression());
if (token === Token.RPAREN) {
break;
}
expect(Token.PIPE);
}
}
consume(Token.RPAREN, 'UnionType should end with )');
return {
type: Syntax.UnionType,
elements: elements
};
}
// ArrayType := '[' ElementTypeList ']'
//
// ElementTypeList :=
// <<empty>>
// | TypeExpression
// | '...' TypeExpression
// | TypeExpression ',' ElementTypeList
function parseArrayType() {
var elements;
consume(Token.LBRACK, 'ArrayType should start with [');
elements = [];
while (token !== Token.RBRACK) {
if (token === Token.REST) {
consume(Token.REST);
elements.push({
type: Syntax.RestType,
expression: parseTypeExpression()
});
break;
} else {
elements.push(parseTypeExpression());
}
if (token !== Token.RBRACK) {
expect(Token.COMMA);
}
}
expect(Token.RBRACK);
return {
type: Syntax.ArrayType,
elements: elements
};
}
function parseFieldName() {
var v = value;
if (token === Token.NAME || token === Token.STRING) {
next();
return v;
}
if (token === Token.NUMBER) {
consume(Token.NUMBER);
return String(v);
}
throw 'unexpected token';
}
// FieldType :=
// FieldName
// | FieldName ':' TypeExpression
//
// FieldName :=
// NameExpression
// | StringLiteral
// | NumberLiteral
// | ReservedIdentifier
function parseFieldType() {
var key;
key = parseFieldName();
if (token === Token.COLON) {
consume(Token.COLON);
return {
type: Syntax.FieldType,
key: key,
value: parseTypeExpression()
};
}
return {
type: Syntax.FieldType,
key: key,
value: null
};
}
// RecordType := '{' FieldTypeList '}'
//
// FieldTypeList :=
// <<empty>>
// | FieldType
// | FieldType ',' FieldTypeList
function parseRecordType() {
var fields, field;
consume(Token.LBRACE, 'RecordType should start with {');
fields = [];
if (token === Token.COMMA) {
consume(Token.COMMA);
} else {
while (token !== Token.RBRACE) {
fields.push(parseFieldType());
if (token !== Token.RBRACE) {
expect(Token.COMMA);
}
}
}
expect(Token.RBRACE);
return {
type: Syntax.RecordType,
fields: fields
};
}
function parseNameExpression() {
var name = value;
expect(Token.NAME);
return {
type: Syntax.NameExpression,
name: name
};
}
// TypeExpressionList :=
// TopLevelTypeExpression
// | TopLevelTypeExpression ',' TypeExpressionList
function parseTypeExpressionList() {
var elements = [];
elements.push(parseTop());
while (token === Token.COMMA) {
consume(Token.COMMA);
elements.push(parseTop());
}
return elements;
}
// TypeName :=
// NameExpression
// | NameExpression TypeApplication
//
// TypeApplication :=
// '.<' TypeExpressionList '>'
// | '<' TypeExpressionList '>' // this is extension of doctrine
function parseTypeName() {
var expr, applications;
expr = parseNameExpression();
if (token === Token.DOT_LT || token === Token.LT) {
next();
applications = parseTypeExpressionList();
expect(Token.GT);
return {
type: Syntax.TypeApplication,
expression: expr,
applications: applications
};
}
return expr;
}
// ResultType :=
// <<empty>>
// | ':' void
// | ':' TypeExpression
//
// BNF is above
// but, we remove <<empty>> pattern, so token is always TypeToken::COLON
function parseResultType() {
consume(Token.COLON, 'ResultType should start with :');
if (token === Token.NAME && value === 'void') {
consume(Token.NAME);
return {
type: Syntax.VoidLiteral
};
}
return parseTypeExpression();
}
// ParametersType :=
// RestParameterType
// | NonRestParametersType
// | NonRestParametersType ',' RestParameterType
//
// RestParameterType :=
// '...'
// '...' Identifier
//
// NonRestParametersType :=
// ParameterType ',' NonRestParametersType
// | ParameterType
// | OptionalParametersType
//
// OptionalParametersType :=
// OptionalParameterType
// | OptionalParameterType, OptionalParametersType
//
// OptionalParameterType := ParameterType=
//
// ParameterType := TypeExpression | Identifier ':' TypeExpression
//
// Identifier is "new" or "this"
function parseParametersType() {
var params = [], normal = true, expr;
while (token !== Token.RPAREN) {
if (token === Token.REST) {
// RestParameterType
consume(Token.REST);
expr = null;
if (token !== Token.RPAREN) {
expr = parseNameExpression();
}
params.push({
type: Syntax.RestType,
expression: expr
});
break;
}
expr = parseTypeExpression();
if (expr.type === Syntax.NameExpression && token === Token.COLON) {
// Identifier ':' TypeExpression
consume(Token.COLON);
expr = {
type: Syntax.ParameterType,
name: expr.name,
expression: parseTypeExpression()
};
}
if (token === Token.EQUAL) {
consume(Token.EQUAL);
expr = {
type: Syntax.OptionalType,
expression: expr
};
normal = false;
} else {
if (!normal) {
throw 'unexpected token';
}
}
params.push(expr);
if (token !== Token.RPAREN) {
expect(Token.COMMA);
}
}
return params;
}
// FunctionType := 'function' FunctionSignatureType
//
// FunctionSignatureType :=
// | TypeParameters '(' ')' ResultType
// | TypeParameters '(' ParametersType ')' ResultType
// | TypeParameters '(' 'this' ':' TypeName ')' ResultType
// | TypeParameters '(' 'this' ':' TypeName ',' ParametersType ')' ResultType
function parseFunctionType() {
var isNew, thisBinding, params, result;
assert(token === Token.NAME && value === 'function', 'FunctionType should start with \'function\'');
consume(Token.NAME);
// Google Closure Compiler is not implementing TypeParameters.
// So we do not. if we don't get '(', we see it as error.
expect(Token.LPAREN);
isNew = false;
params = [];
thisBinding = null;
if (token !== Token.RPAREN) {
// ParametersType or 'this'
if (token === Token.NAME &&
(value === 'this' || value === 'new')) {
// 'this' or 'new'
// 'new' is Closure Compiler extension
isNew = value === 'new';
consume(Token.NAME);
expect(Token.COLON);
thisBinding = parseTypeName();
if (token === Token.COMMA) {
consume(Token.COMMA);
params = parseParametersType();
}
} else {
params = parseParametersType();
}
}
expect(Token.RPAREN);
result = null;
if (token === Token.COLON) {
result = parseResultType();
}
return {
type: Syntax.FunctionType,
params: params,
result: result,
'this': thisBinding,
'new': isNew
};
}
// BasicTypeExpression :=
// '*'
// | 'null'
// | 'undefined'
// | TypeName
// | FunctionType
// | UnionType
// | RecordType
// | ArrayType
function parseBasicTypeExpression() {
switch (token) {
case Token.STAR:
consume(Token.STAR);
return {
type: Syntax.AllLiteral
};
case Token.LPAREN:
return parseUnionType();
case Token.LBRACK:
return parseArrayType();
case Token.LBRACE:
return parseRecordType();
case Token.NAME:
if (value === 'null') {
consume(Token.NAME);
return {
type: Syntax.NullLiteral
};
}
if (value === 'undefined') {
consume(Token.NAME);
return {
type: Syntax.UndefinedLiteral
};
}
if (value === 'function') {
return parseFunctionType();
}
return parseTypeName();
default:
throw "unexpected token";
}
}
// TypeExpression :=
// BasicTypeExpression
// | '?' BasicTypeExpression
// | '!' BasicTypeExpression
// | BasicTypeExpression '?'
// | BasicTypeExpression '!'
// | '?'
function parseTypeExpression() {
var expr;
if (token === Token.QUESTION) {
consume(Token.QUESTION);
if (token === Token.COMMA || token === Token.EQUAL || token === Token.RBRACE ||
token === Token.RPAREN || token === Token.PIPE || token === Token.EOF) {
return {
type: Syntax.NullableLiteral
};
}
return {
type: Syntax.NullableType,
expression: parseBasicTypeExpression(),
prefix: true
};
}
if (token === Token.BANG) {
consume(Token.BANG);
return {
type: Syntax.NonNullableType,
expression: parseBasicTypeExpression(),
prefix: true
};
}
expr = parseBasicTypeExpression();
if (token === Token.BANG) {
consume(Token.BANG);
return {
type: Syntax.NonNullableType,
expression: expr,
prefix: false
};
}
if (token === Token.QUESTION) {
consume(Token.QUESTION);
return {
type: Syntax.NullableType,
expression: expr,
prefix: false
};
}
return expr;
}
// TopLevelTypeExpression :=
// TypeExpression
// | TypeUnionList
//
// This rule is Google Closure Compiler extension, not ES4
// like,
// { number | string }
// If strict to ES4, we should write it as
// { (number|string) }
function parseTop() {
var expr, elements;
expr = parseTypeExpression();
if (token !== Token.PIPE) {
return expr;
}
elements = [ expr ];
consume(Token.PIPE);
while (true) {
elements.push(parseTypeExpression());
if (token !== Token.PIPE) {
break;
}
consume(Token.PIPE);
}
return {
type: Syntax.UnionType,
elements: elements
};
}
function parseTopParamType() {
var expr;
if (token === Token.REST) {
consume(Token.REST);
return {
type: Syntax.RestType,
expression: parseTop()
};
}
expr = parseTop();
if (token === Token.EQUAL) {
consume(Token.EQUAL);
return {
type: Syntax.OptionalType,
expression: expr
};
}
return expr;
}
function parseType(src, opt) {
var expr;
source = src;
length = source.length;
index = 0;
previous = 0;
if (!CanAccessStringByIndex) {
source = source.split('');
}
next();
expr = parseTop();
if (opt && opt.midstream) {
return {
expression: expr,
index: previous
};
}
if (token !== Token.EOF) {
throw 'not reach to EOF';
}
return expr;
}
function parseParamType(src, opt) {
var expr;
source = src;
length = source.length;
index = 0;
previous = 0;
if (!CanAccessStringByIndex) {
source = source.split('');
}
next();
expr = parseTopParamType();
if (opt && opt.midstream) {
return {
expression: expr,
index: previous
};
}
if (token !== Token.EOF) {
throw 'not reach to EOF';
}
return expr;
}
exports.parseType = parseType;
exports.parseParamType = parseParamType;
}(typed = {}));
// JSDoc Tag Parser
(function (exports) {
var index,
length,
source,
recoverable;
function advance() {
var ch = source[index];
index += 1;
return ch;
}
function scanTitle() {
var title = '';
// waste '@'
advance();
while (index < length && isASCIIAlphanumeric(source[index])) {
title += advance();
}
return title;
}
function seekContent() {
var ch, waiting, last = index;
waiting = false;
while (last < length) {
ch = source[last];
if (isLineTerminator(ch)) {
waiting = true;
} else if (waiting) {
if (ch === '@') {
break;
}
if (!isWhiteSpace(ch)) {
waiting = false;
}
}
last += 1;
}
return last;
}
// type expression may have nest brace, such as,
// { { ok: string } }
//
// therefore, scanning type expression with balancing braces.
function parseType(title, last) {
var ch, brace, type, direct = false, res;
// search '{'
while (index < last) {
ch = source[index];
if (isWhiteSpace(ch)) {
advance();
} else if (ch === '{') {
advance();
break;
} else {
// this is direct pattern
direct = true;
break;
}
}
if (!direct) {
// type expression { is found
brace = 0;
type = '';
while (index < last) {
ch = source[index];
if (isLineTerminator(ch)) {
return;
}
if (ch === '}') {
if (brace === 0) {
advance();
break;
} else {
brace -= 1;
}
} else if (ch === '{') {
brace += 1;
}
type += advance();
}
try {
if (title === 'param') {
return typed.parseParamType(type);
}
return typed.parseType(type);
} catch (e1) {
// parse failed
return;
}
} else {
type = sliceSource(source, index, last);
try {
if (title === 'param') {
res = typed.parseParamType(type, { midstream: true });
} else {
res = typed.parseType(type, { midstream: true });
}
index += res.index;
return res.expression;
} catch (e2) {
// parse failed
return;
}
}
}
function parseName(last) {
var range, ch, name, i, len;
// skip white spaces
while (index < last && (isWhiteSpace(source[index]) || isLineTerminator(source[index]))) {
advance();
}
if (index >= last) {
return;
}
if (!isIdentifierStart(source[index])) {
return;
}
name = advance();
while (index < last) {
ch = source[index];
if (isWhiteSpace(ch) || isLineTerminator(ch)) {
advance();
break;
}
if (!isIdentifierPart(ch)) {
return;
}
name += advance();
}
return name;
}
function isTypeParameterRequired(title) {
return title === 'define' || title === 'enum' || title === 'extends' ||
title === 'implements' || title === 'param' || title === 'return' ||
title === 'this' || title === 'type' || title === 'typedef' ||
title === 'throws' || title === 'returns' || title === 'property' ||
title === 'augments';
}
function scanDescription() {
var description = '';
while (index < length && source[index] != '@') {
description += advance();
}
return description;
}
function next() {
var tag, title, type, last, description;
// skip to tag
while (index < length && source[index] !== '@') {
advance();
}
if (index >= length) {
return;
}
assert(source[index] === '@');
// scan title
title = scanTitle();
// empty title
if (!title && !recoverable) {
return;
}
// seek to content last index
last = seekContent(title);
tag = {
title: title,
description: null
};
// type required titles
if (isTypeParameterRequired(title)) {
tag.type = parseType(title, last);
if (!tag.type && !recoverable) {
return;
}
}
// param, property requires name
if (title === 'param' || title === 'property') {
tag.name = parseName(last);
if (!tag.name && !recoverable) {
return;
}
}
// slice description
description = trim(sliceSource(source, index, last));
if (description) {
tag.description = description;
}
index = last;
return tag;
}
function stringToArray(str) {
return str.split('');
}
function parse(comment, options) {
var tags = [], tag, description, interestingTags;
if (options === undefined) {
options = {};
}
if (typeof options.unwrap === 'boolean' && options.unwrap) {
source = unwrapComment(comment);
} else {
source = comment;
}
// array of relevant tags
if (options.tags) {
if (isArray(options.tags)) {
interestingTags = { };
for (var i = 0; i < options.tags.length; i++) {
if (typeof options.tags[i] === 'string') {
interestingTags[options.tags[i]] = true;
} else {
throw new Error('Invalid "tags" parameter: ' + options.tags);
}
}
} else {
throw new Error('Invalid "tags" parameter: ' + options.tags);
}
}
if (!CanAccessStringByIndex) {
source = source.split('');
}
length = source.length;
index = 0;
recoverable = options.recoverable;
description = trim(scanDescription());
while (true) {
tag = next();
if (!tag) {
break;
}
if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
tags.push(tag);
}
}
return {
description: description,
tags: tags
};
}
exports.parse = parse;
}(jsdoc = {}));
exports.version = VERSION;
exports.parse = jsdoc.parse;
exports.parseType = typed.parseType;
exports.parseParamType = typed.parseParamType;
exports.unwrapComment = unwrapComment;
exports.Syntax = shallowCopy(typed.Syntax);
}(typeof exports === 'undefined' ? (doctrine = {}) : exports));
/* vim: set sw=4 ts=4 et tw=80 : */