summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/node_modules/doctrine/lib/doctrine.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/node_modules/doctrine/lib/doctrine.js')
-rw-r--r--tools/node_modules/eslint/node_modules/doctrine/lib/doctrine.js891
1 files changed, 891 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/node_modules/doctrine/lib/doctrine.js b/tools/node_modules/eslint/node_modules/doctrine/lib/doctrine.js
new file mode 100644
index 0000000000..bdaa0e0788
--- /dev/null
+++ b/tools/node_modules/eslint/node_modules/doctrine/lib/doctrine.js
@@ -0,0 +1,891 @@
+/*
+ * @fileoverview Main Doctrine object
+ * @author Yusuke Suzuki <utatane.tea@gmail.com>
+ * @author Dan Tao <daniel.tao@gmail.com>
+ * @author Andrew Eisenberg <andrew@eisenberg.as>
+ */
+
+(function () {
+ 'use strict';
+
+ var typed,
+ utility,
+ jsdoc,
+ esutils,
+ hasOwnProperty;
+
+ esutils = require('esutils');
+ typed = require('./typed');
+ utility = require('./utility');
+
+ function sliceSource(source, index, last) {
+ return source.slice(index, last);
+ }
+
+ hasOwnProperty = (function () {
+ var func = Object.prototype.hasOwnProperty;
+ return function hasOwnProperty(obj, name) {
+ return func.call(obj, name);
+ };
+ }());
+
+ function shallowCopy(obj) {
+ var ret = {}, key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ ret[key] = obj[key];
+ }
+ }
+ return ret;
+ }
+
+ function isASCIIAlphanumeric(ch) {
+ return (ch >= 0x61 /* 'a' */ && ch <= 0x7A /* 'z' */) ||
+ (ch >= 0x41 /* 'A' */ && ch <= 0x5A /* 'Z' */) ||
+ (ch >= 0x30 /* '0' */ && ch <= 0x39 /* '9' */);
+ }
+
+ function isParamTitle(title) {
+ return title === 'param' || title === 'argument' || title === 'arg';
+ }
+
+ function isReturnTitle(title) {
+ return title === 'return' || title === 'returns';
+ }
+
+ function isProperty(title) {
+ return title === 'property' || title === 'prop';
+ }
+
+ function isNameParameterRequired(title) {
+ return isParamTitle(title) || isProperty(title) ||
+ title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires';
+ }
+
+ function isAllowedName(title) {
+ return isNameParameterRequired(title) || title === 'const' || title === 'constant';
+ }
+
+ function isAllowedNested(title) {
+ return isProperty(title) || isParamTitle(title);
+ }
+
+ function isAllowedOptional(title) {
+ return isProperty(title) || isParamTitle(title);
+ }
+
+ function isTypeParameterRequired(title) {
+ return isParamTitle(title) || isReturnTitle(title) ||
+ title === 'define' || title === 'enum' ||
+ title === 'implements' || title === 'this' ||
+ title === 'type' || title === 'typedef' || isProperty(title);
+ }
+
+ // Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required
+ // This would require changes to 'parseType'
+ function isAllowedType(title) {
+ return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' ||
+ title === 'namespace' || title === 'member' || title === 'var' || title === 'module' ||
+ title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' ||
+ title === 'public' || title === 'private' || title === 'protected';
+ }
+
+ 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.charCodeAt(index);
+ switch (mode) {
+ case BEFORE_STAR:
+ if (esutils.code.isLineTerminator(ch)) {
+ result += String.fromCharCode(ch);
+ } else if (ch === 0x2A /* '*' */) {
+ mode = STAR;
+ } else if (!esutils.code.isWhiteSpace(ch)) {
+ result += String.fromCharCode(ch);
+ mode = AFTER_STAR;
+ }
+ break;
+
+ case STAR:
+ if (!esutils.code.isWhiteSpace(ch)) {
+ result += String.fromCharCode(ch);
+ }
+ mode = esutils.code.isLineTerminator(ch) ? BEFORE_STAR : AFTER_STAR;
+ break;
+
+ case AFTER_STAR:
+ result += String.fromCharCode(ch);
+ if (esutils.code.isLineTerminator(ch)) {
+ mode = BEFORE_STAR;
+ }
+ break;
+ }
+ index += 1;
+ }
+
+ return result.replace(/\s+$/, '');
+ }
+
+ // JSDoc Tag Parser
+
+ (function (exports) {
+ var Rules,
+ index,
+ lineNumber,
+ length,
+ source,
+ recoverable,
+ sloppy,
+ strict;
+
+ function advance() {
+ var ch = source.charCodeAt(index);
+ index += 1;
+ if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D /* '\r' */ && source.charCodeAt(index) === 0x0A /* '\n' */)) {
+ lineNumber += 1;
+ }
+ return String.fromCharCode(ch);
+ }
+
+ function scanTitle() {
+ var title = '';
+ // waste '@'
+ advance();
+
+ while (index < length && isASCIIAlphanumeric(source.charCodeAt(index))) {
+ title += advance();
+ }
+
+ return title;
+ }
+
+ function seekContent() {
+ var ch, waiting, last = index;
+
+ waiting = false;
+ while (last < length) {
+ ch = source.charCodeAt(last);
+ if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D /* '\r' */ && source.charCodeAt(last + 1) === 0x0A /* '\n' */)) {
+ waiting = true;
+ } else if (waiting) {
+ if (ch === 0x40 /* '@' */) {
+ break;
+ }
+ if (!esutils.code.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;
+
+
+ // search '{'
+ while (index < last) {
+ ch = source.charCodeAt(index);
+ if (esutils.code.isWhiteSpace(ch)) {
+ advance();
+ } else if (ch === 0x7B /* '{' */) {
+ advance();
+ break;
+ } else {
+ // this is direct pattern
+ direct = true;
+ break;
+ }
+ }
+
+
+ if (direct) {
+ return null;
+ }
+
+ // type expression { is found
+ brace = 1;
+ type = '';
+ while (index < last) {
+ ch = source.charCodeAt(index);
+ if (esutils.code.isLineTerminator(ch)) {
+ advance();
+ } else {
+ if (ch === 0x7D /* '}' */) {
+ brace -= 1;
+ if (brace === 0) {
+ advance();
+ break;
+ }
+ } else if (ch === 0x7B /* '{' */) {
+ brace += 1;
+ }
+ type += advance();
+ }
+ }
+
+ if (brace !== 0) {
+ // braces is not balanced
+ return utility.throwError('Braces are not balanced');
+ }
+
+ if (isAllowedOptional(title)) {
+ return typed.parseParamType(type);
+ }
+
+ return typed.parseType(type);
+ }
+
+ function scanIdentifier(last) {
+ var identifier;
+ if (!esutils.code.isIdentifierStartES5(source.charCodeAt(index)) && !source[index].match(/[0-9]/)) {
+ return null;
+ }
+ identifier = advance();
+ while (index < last && esutils.code.isIdentifierPartES5(source.charCodeAt(index))) {
+ identifier += advance();
+ }
+ return identifier;
+ }
+
+ function skipWhiteSpace(last) {
+ while (index < last && (esutils.code.isWhiteSpace(source.charCodeAt(index)) || esutils.code.isLineTerminator(source.charCodeAt(index)))) {
+ advance();
+ }
+ }
+
+ function parseName(last, allowBrackets, allowNestedParams) {
+ var name = '',
+ useBrackets,
+ insideString;
+
+
+ skipWhiteSpace(last);
+
+ if (index >= last) {
+ return null;
+ }
+
+ if (source.charCodeAt(index) === 0x5B /* '[' */) {
+ if (allowBrackets) {
+ useBrackets = true;
+ name = advance();
+ } else {
+ return null;
+ }
+ }
+
+ name += scanIdentifier(last);
+
+ if (allowNestedParams) {
+ if (source.charCodeAt(index) === 0x3A /* ':' */ && (
+ name === 'module' ||
+ name === 'external' ||
+ name === 'event')) {
+ name += advance();
+ name += scanIdentifier(last);
+
+ }
+ if(source.charCodeAt(index) === 0x5B /* '[' */ && source.charCodeAt(index + 1) === 0x5D /* ']' */){
+ name += advance();
+ name += advance();
+ }
+ while (source.charCodeAt(index) === 0x2E /* '.' */ ||
+ source.charCodeAt(index) === 0x2F /* '/' */ ||
+ source.charCodeAt(index) === 0x23 /* '#' */ ||
+ source.charCodeAt(index) === 0x2D /* '-' */ ||
+ source.charCodeAt(index) === 0x7E /* '~' */) {
+ name += advance();
+ name += scanIdentifier(last);
+ }
+ }
+
+ if (useBrackets) {
+ skipWhiteSpace(last);
+ // do we have a default value for this?
+ if (source.charCodeAt(index) === 0x3D /* '=' */) {
+ // consume the '='' symbol
+ name += advance();
+ skipWhiteSpace(last);
+
+ var ch;
+ var bracketDepth = 1;
+
+ // scan in the default value
+ while (index < last) {
+ ch = source.charCodeAt(index);
+
+ if (esutils.code.isWhiteSpace(ch)) {
+ if (!insideString) {
+ skipWhiteSpace(last);
+ ch = source.charCodeAt(index);
+ }
+ }
+
+ if (ch === 0x27 /* ''' */) {
+ if (!insideString) {
+ insideString = '\'';
+ } else {
+ if (insideString === '\'') {
+ insideString = '';
+ }
+ }
+ }
+
+ if (ch === 0x22 /* '"' */) {
+ if (!insideString) {
+ insideString = '"';
+ } else {
+ if (insideString === '"') {
+ insideString = '';
+ }
+ }
+ }
+
+ if (ch === 0x5B /* '[' */) {
+ bracketDepth++;
+ } else if (ch === 0x5D /* ']' */ &&
+ --bracketDepth === 0) {
+ break;
+ }
+
+ name += advance();
+ }
+ }
+
+ skipWhiteSpace(last);
+
+ if (index >= last || source.charCodeAt(index) !== 0x5D /* ']' */) {
+ // we never found a closing ']'
+ return null;
+ }
+
+ // collect the last ']'
+ name += advance();
+ }
+
+ return name;
+ }
+
+ function skipToTag() {
+ while (index < length && source.charCodeAt(index) !== 0x40 /* '@' */) {
+ advance();
+ }
+ if (index >= length) {
+ return false;
+ }
+ utility.assert(source.charCodeAt(index) === 0x40 /* '@' */);
+ return true;
+ }
+
+ function TagParser(options, title) {
+ this._options = options;
+ this._title = title.toLowerCase();
+ this._tag = {
+ title: title,
+ description: null
+ };
+ if (this._options.lineNumbers) {
+ this._tag.lineNumber = lineNumber;
+ }
+ this._last = 0;
+ // space to save special information for title parsers.
+ this._extra = { };
+ }
+
+ // addError(err, ...)
+ TagParser.prototype.addError = function addError(errorText) {
+ var args = Array.prototype.slice.call(arguments, 1),
+ msg = errorText.replace(
+ /%(\d)/g,
+ function (whole, index) {
+ utility.assert(index < args.length, 'Message reference must be in range');
+ return args[index];
+ }
+ );
+
+ if (!this._tag.errors) {
+ this._tag.errors = [];
+ }
+ if (strict) {
+ utility.throwError(msg);
+ }
+ this._tag.errors.push(msg);
+ return recoverable;
+ };
+
+ TagParser.prototype.parseType = function () {
+ // type required titles
+ if (isTypeParameterRequired(this._title)) {
+ try {
+ this._tag.type = parseType(this._title, this._last);
+ if (!this._tag.type) {
+ if (!isParamTitle(this._title) && !isReturnTitle(this._title)) {
+ if (!this.addError('Missing or invalid tag type')) {
+ return false;
+ }
+ }
+ }
+ } catch (error) {
+ this._tag.type = null;
+ if (!this.addError(error.message)) {
+ return false;
+ }
+ }
+ } else if (isAllowedType(this._title)) {
+ // optional types
+ try {
+ this._tag.type = parseType(this._title, this._last);
+ } catch (e) {
+ //For optional types, lets drop the thrown error when we hit the end of the file
+ }
+ }
+ return true;
+ };
+
+ TagParser.prototype._parseNamePath = function (optional) {
+ var name;
+ name = parseName(this._last, sloppy && isAllowedOptional(this._title), true);
+ if (!name) {
+ if (!optional) {
+ if (!this.addError('Missing or invalid tag name')) {
+ return false;
+ }
+ }
+ }
+ this._tag.name = name;
+ return true;
+ };
+
+ TagParser.prototype.parseNamePath = function () {
+ return this._parseNamePath(false);
+ };
+
+ TagParser.prototype.parseNamePathOptional = function () {
+ return this._parseNamePath(true);
+ };
+
+
+ TagParser.prototype.parseName = function () {
+ var assign, name;
+
+ // param, property requires name
+ if (isAllowedName(this._title)) {
+ this._tag.name = parseName(this._last, sloppy && isAllowedOptional(this._title), isAllowedNested(this._title));
+ if (!this._tag.name) {
+ if (!isNameParameterRequired(this._title)) {
+ return true;
+ }
+
+ // it's possible the name has already been parsed but interpreted as a type
+ // it's also possible this is a sloppy declaration, in which case it will be
+ // fixed at the end
+ if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) {
+ this._extra.name = this._tag.type;
+ this._tag.name = this._tag.type.name;
+ this._tag.type = null;
+ } else {
+ if (!this.addError('Missing or invalid tag name')) {
+ return false;
+ }
+ }
+ } else {
+ name = this._tag.name;
+ if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') {
+ // extract the default value if there is one
+ // example: @param {string} [somebody=John Doe] description
+ assign = name.substring(1, name.length - 1).split('=');
+ if (assign.length > 1) {
+ this._tag['default'] = assign.slice(1).join('=');
+ }
+ this._tag.name = assign[0];
+
+ // convert to an optional type
+ if (this._tag.type && this._tag.type.type !== 'OptionalType') {
+ this._tag.type = {
+ type: 'OptionalType',
+ expression: this._tag.type
+ };
+ }
+ }
+ }
+ }
+
+
+ return true;
+ };
+
+ TagParser.prototype.parseDescription = function parseDescription() {
+ var description = sliceSource(source, index, this._last).trim();
+ if (description) {
+ if ((/^-\s+/).test(description)) {
+ description = description.substring(2);
+ }
+ this._tag.description = description;
+ }
+ return true;
+ };
+
+ TagParser.prototype.parseCaption = function parseDescription() {
+ var description = sliceSource(source, index, this._last).trim();
+ var captionStartTag = '<caption>';
+ var captionEndTag = '</caption>';
+ var captionStart = description.indexOf(captionStartTag);
+ var captionEnd = description.indexOf(captionEndTag);
+ if (captionStart >= 0 && captionEnd >= 0) {
+ this._tag.caption = description.substring(
+ captionStart + captionStartTag.length, captionEnd).trim();
+ this._tag.description = description.substring(captionEnd + captionEndTag.length).trim();
+ } else {
+ this._tag.description = description;
+ }
+ return true;
+ };
+
+ TagParser.prototype.parseKind = function parseKind() {
+ var kind, kinds;
+ kinds = {
+ 'class': true,
+ 'constant': true,
+ 'event': true,
+ 'external': true,
+ 'file': true,
+ 'function': true,
+ 'member': true,
+ 'mixin': true,
+ 'module': true,
+ 'namespace': true,
+ 'typedef': true
+ };
+ kind = sliceSource(source, index, this._last).trim();
+ this._tag.kind = kind;
+ if (!hasOwnProperty(kinds, kind)) {
+ if (!this.addError('Invalid kind name \'%0\'', kind)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ TagParser.prototype.parseAccess = function parseAccess() {
+ var access;
+ access = sliceSource(source, index, this._last).trim();
+ this._tag.access = access;
+ if (access !== 'private' && access !== 'protected' && access !== 'public') {
+ if (!this.addError('Invalid access name \'%0\'', access)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ TagParser.prototype.parseThis = function parseThis() {
+ // this name may be a name expression (e.g. {foo.bar}),
+ // an union (e.g. {foo.bar|foo.baz}) or a name path (e.g. foo.bar)
+ var value = sliceSource(source, index, this._last).trim();
+ if (value && value.charAt(0) === '{') {
+ var gotType = this.parseType();
+ if (gotType && this._tag.type.type === 'NameExpression' || this._tag.type.type === 'UnionType') {
+ this._tag.name = this._tag.type.name;
+ return true;
+ } else {
+ return this.addError('Invalid name for this');
+ }
+ } else {
+ return this.parseNamePath();
+ }
+ };
+
+ TagParser.prototype.parseVariation = function parseVariation() {
+ var variation, text;
+ text = sliceSource(source, index, this._last).trim();
+ variation = parseFloat(text, 10);
+ this._tag.variation = variation;
+ if (isNaN(variation)) {
+ if (!this.addError('Invalid variation \'%0\'', text)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ TagParser.prototype.ensureEnd = function () {
+ var shouldBeEmpty = sliceSource(source, index, this._last).trim();
+ if (shouldBeEmpty) {
+ if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ TagParser.prototype.epilogue = function epilogue() {
+ var description;
+
+ description = this._tag.description;
+ // un-fix potentially sloppy declaration
+ if (isAllowedOptional(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
+ this._tag.type = this._extra.name;
+ if (!this._tag.name) {
+ this._tag.name = undefined;
+ }
+
+ if (!sloppy) {
+ if (!this.addError('Missing or invalid tag name')) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ };
+
+ Rules = {
+ // http://usejsdoc.org/tags-access.html
+ 'access': ['parseAccess'],
+ // http://usejsdoc.org/tags-alias.html
+ 'alias': ['parseNamePath', 'ensureEnd'],
+ // http://usejsdoc.org/tags-augments.html
+ 'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-constructor.html
+ 'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // Synonym: http://usejsdoc.org/tags-constructor.html
+ 'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // Synonym: http://usejsdoc.org/tags-extends.html
+ 'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-example.html
+ 'example': ['parseCaption'],
+ // http://usejsdoc.org/tags-deprecated.html
+ 'deprecated': ['parseDescription'],
+ // http://usejsdoc.org/tags-global.html
+ 'global': ['ensureEnd'],
+ // http://usejsdoc.org/tags-inner.html
+ 'inner': ['ensureEnd'],
+ // http://usejsdoc.org/tags-instance.html
+ 'instance': ['ensureEnd'],
+ // http://usejsdoc.org/tags-kind.html
+ 'kind': ['parseKind'],
+ // http://usejsdoc.org/tags-mixes.html
+ 'mixes': ['parseNamePath', 'ensureEnd'],
+ // http://usejsdoc.org/tags-mixin.html
+ 'mixin': ['parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-member.html
+ 'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-method.html
+ 'method': ['parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-module.html
+ 'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // Synonym: http://usejsdoc.org/tags-method.html
+ 'func': ['parseNamePathOptional', 'ensureEnd'],
+ // Synonym: http://usejsdoc.org/tags-method.html
+ 'function': ['parseNamePathOptional', 'ensureEnd'],
+ // Synonym: http://usejsdoc.org/tags-member.html
+ 'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-name.html
+ 'name': ['parseNamePath', 'ensureEnd'],
+ // http://usejsdoc.org/tags-namespace.html
+ 'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
+ // http://usejsdoc.org/tags-private.html
+ 'private': ['parseType', 'parseDescription'],
+ // http://usejsdoc.org/tags-protected.html
+ 'protected': ['parseType', 'parseDescription'],
+ // http://usejsdoc.org/tags-public.html
+ 'public': ['parseType', 'parseDescription'],
+ // http://usejsdoc.org/tags-readonly.html
+ 'readonly': ['ensureEnd'],
+ // http://usejsdoc.org/tags-requires.html
+ 'requires': ['parseNamePath', 'ensureEnd'],
+ // http://usejsdoc.org/tags-since.html
+ 'since': ['parseDescription'],
+ // http://usejsdoc.org/tags-static.html
+ 'static': ['ensureEnd'],
+ // http://usejsdoc.org/tags-summary.html
+ 'summary': ['parseDescription'],
+ // http://usejsdoc.org/tags-this.html
+ 'this': ['parseThis', 'ensureEnd'],
+ // http://usejsdoc.org/tags-todo.html
+ 'todo': ['parseDescription'],
+ // http://usejsdoc.org/tags-typedef.html
+ 'typedef': ['parseType', 'parseNamePathOptional'],
+ // http://usejsdoc.org/tags-variation.html
+ 'variation': ['parseVariation'],
+ // http://usejsdoc.org/tags-version.html
+ 'version': ['parseDescription']
+ };
+
+ TagParser.prototype.parse = function parse() {
+ var i, iz, sequences, method;
+
+
+ // empty title
+ if (!this._title) {
+ if (!this.addError('Missing or invalid title')) {
+ return null;
+ }
+ }
+
+ // Seek to content last index.
+ this._last = seekContent(this._title);
+
+ if (hasOwnProperty(Rules, this._title)) {
+ sequences = Rules[this._title];
+ } else {
+ // default sequences
+ sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue'];
+ }
+
+ for (i = 0, iz = sequences.length; i < iz; ++i) {
+ method = sequences[i];
+ if (!this[method]()) {
+ return null;
+ }
+ }
+
+ return this._tag;
+ };
+
+ function parseTag(options) {
+ var title, parser, tag;
+
+ // skip to tag
+ if (!skipToTag()) {
+ return null;
+ }
+
+ // scan title
+ title = scanTitle();
+
+ // construct tag parser
+ parser = new TagParser(options, title);
+ tag = parser.parse();
+
+ // Seek global index to end of this tag.
+ while (index < parser._last) {
+ advance();
+ }
+
+ return tag;
+ }
+
+ //
+ // Parse JSDoc
+ //
+
+ function scanJSDocDescription(preserveWhitespace) {
+ var description = '', ch, atAllowed;
+
+ atAllowed = true;
+ while (index < length) {
+ ch = source.charCodeAt(index);
+
+ if (atAllowed && ch === 0x40 /* '@' */) {
+ break;
+ }
+
+ if (esutils.code.isLineTerminator(ch)) {
+ atAllowed = true;
+ } else if (atAllowed && !esutils.code.isWhiteSpace(ch)) {
+ atAllowed = false;
+ }
+
+ description += advance();
+ }
+
+ return preserveWhitespace ? description : description.trim();
+ }
+
+ function parse(comment, options) {
+ var tags = [], tag, description, interestingTags, i, iz;
+
+ 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 (Array.isArray(options.tags)) {
+ interestingTags = { };
+ for (i = 0, iz = options.tags.length; i < iz; i++) {
+ if (typeof options.tags[i] === 'string') {
+ interestingTags[options.tags[i]] = true;
+ } else {
+ utility.throwError('Invalid "tags" parameter: ' + options.tags);
+ }
+ }
+ } else {
+ utility.throwError('Invalid "tags" parameter: ' + options.tags);
+ }
+ }
+
+ length = source.length;
+ index = 0;
+ lineNumber = 0;
+ recoverable = options.recoverable;
+ sloppy = options.sloppy;
+ strict = options.strict;
+
+ description = scanJSDocDescription(options.preserveWhitespace);
+
+ while (true) {
+ tag = parseTag(options);
+ if (!tag) {
+ break;
+ }
+ if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
+ tags.push(tag);
+ }
+ }
+
+ return {
+ description: description,
+ tags: tags
+ };
+ }
+ exports.parse = parse;
+ }(jsdoc = {}));
+
+ exports.version = utility.VERSION;
+ exports.parse = jsdoc.parse;
+ exports.parseType = typed.parseType;
+ exports.parseParamType = typed.parseParamType;
+ exports.unwrapComment = unwrapComment;
+ exports.Syntax = shallowCopy(typed.Syntax);
+ exports.Error = utility.DoctrineError;
+ exports.type = {
+ Syntax: exports.Syntax,
+ parseType: typed.parseType,
+ parseParamType: typed.parseParamType,
+ stringify: typed.stringify
+ };
+}());
+/* vim: set sw=4 ts=4 et tw=80 : */