123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898 |
- (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 && ch <= 0x7A ) ||
- (ch >= 0x41 && ch <= 0x5A ) ||
- (ch >= 0x30 && ch <= 0x39 );
- }
- 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);
- }
-
-
- 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';
- }
-
- var WHITESPACE = '[ \\f\\t\\v\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]';
- var STAR_MATCHER = '(' + WHITESPACE + '*(?:\\*' + WHITESPACE + '?)?)(.+|[\r\n\u2028\u2029])';
- function unwrapComment(doc) {
-
-
-
-
- return doc.
-
- replace(/^\/\*\*?/, '').
-
- replace(/\*\/$/, '').
-
- replace(new RegExp(STAR_MATCHER, 'g'), '$2').
-
- replace(/\s*$/, '');
- }
-
- function convertUnwrappedCommentIndex(originalSource, unwrappedIndex) {
- var replacedSource = originalSource.replace(/^\/\*\*?/, '');
- var numSkippedChars = 0;
- var matcher = new RegExp(STAR_MATCHER, 'g');
- var match;
- while ((match = matcher.exec(replacedSource))) {
- numSkippedChars += match[1].length;
- if (match.index + match[0].length > unwrappedIndex + numSkippedChars) {
- return unwrappedIndex + numSkippedChars + originalSource.length - replacedSource.length;
- }
- }
- return originalSource.replace(/\*\/$/, '').replace(/\s*$/, '').length;
- }
-
- (function (exports) {
- var Rules,
- index,
- lineNumber,
- length,
- source,
- originalSource,
- recoverable,
- sloppy,
- strict;
- function advance() {
- var ch = source.charCodeAt(index);
- index += 1;
- if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D && source.charCodeAt(index) === 0x0A )) {
- lineNumber += 1;
- }
- return String.fromCharCode(ch);
- }
- function scanTitle() {
- var title = '';
-
- 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 && source.charCodeAt(last + 1) === 0x0A )) {
- waiting = true;
- } else if (waiting) {
- if (ch === 0x40 ) {
- break;
- }
- if (!esutils.code.isWhiteSpace(ch)) {
- waiting = false;
- }
- }
- last += 1;
- }
- return last;
- }
-
-
-
-
- function parseType(title, last, addRange) {
- var ch, brace, type, startIndex, direct = false;
-
- while (index < last) {
- ch = source.charCodeAt(index);
- if (esutils.code.isWhiteSpace(ch)) {
- advance();
- } else if (ch === 0x7B ) {
- advance();
- break;
- } else {
-
- direct = true;
- break;
- }
- }
- if (direct) {
- return null;
- }
-
- 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;
- }
- if (type === '') {
- startIndex = index;
- }
- type += advance();
- }
- }
- if (brace !== 0) {
-
- return utility.throwError('Braces are not balanced');
- }
- if (isAllowedOptional(title)) {
- return typed.parseParamType(type, {startIndex: convertIndex(startIndex), range: addRange});
- }
- return typed.parseType(type, {startIndex: convertIndex(startIndex), range: addRange});
- }
- 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);
-
- if (source.charCodeAt(index) === 0x3D ) {
-
- name += advance();
- skipWhiteSpace(last);
- var ch;
- var bracketDepth = 1;
-
- 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 ) {
-
- return null;
- }
-
- 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 convertIndex(rangeIndex) {
- if (source === originalSource) {
- return rangeIndex;
- }
- return convertUnwrappedCommentIndex(originalSource, rangeIndex);
- }
- 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._first = index - title.length - 1;
- this._last = 0;
-
- this._extra = { };
- }
-
- 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 () {
-
- if (isTypeParameterRequired(this._title)) {
- try {
- this._tag.type = parseType(this._title, this._last, this._options.range);
- 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)) {
-
- try {
- this._tag.type = parseType(this._title, this._last, this._options.range);
- } catch (e) {
-
- }
- }
- 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;
-
- 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;
- }
-
-
-
- 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) === ']') {
-
-
- assign = name.substring(1, name.length - 1).split('=');
- if (assign.length > 1) {
- this._tag['default'] = assign.slice(1).join('=');
- }
- this._tag.name = assign[0];
-
- 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() {
-
-
- 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;
-
- 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 = {
-
- 'access': ['parseAccess'],
-
- 'alias': ['parseNamePath', 'ensureEnd'],
-
- 'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'example': ['parseCaption'],
-
- 'deprecated': ['parseDescription'],
-
- 'global': ['ensureEnd'],
-
- 'inner': ['ensureEnd'],
-
- 'instance': ['ensureEnd'],
-
- 'kind': ['parseKind'],
-
- 'mixes': ['parseNamePath', 'ensureEnd'],
-
- 'mixin': ['parseNamePathOptional', 'ensureEnd'],
-
- 'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'method': ['parseNamePathOptional', 'ensureEnd'],
-
- 'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'func': ['parseNamePathOptional', 'ensureEnd'],
-
- 'function': ['parseNamePathOptional', 'ensureEnd'],
-
- 'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'name': ['parseNamePath', 'ensureEnd'],
-
- 'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
-
- 'private': ['parseType', 'parseDescription'],
-
- 'protected': ['parseType', 'parseDescription'],
-
- 'public': ['parseType', 'parseDescription'],
-
- 'readonly': ['ensureEnd'],
-
- 'requires': ['parseNamePath', 'ensureEnd'],
-
- 'since': ['parseDescription'],
-
- 'static': ['ensureEnd'],
-
- 'summary': ['parseDescription'],
-
- 'this': ['parseThis', 'ensureEnd'],
-
- 'todo': ['parseDescription'],
-
- 'typedef': ['parseType', 'parseNamePathOptional'],
-
- 'variation': ['parseVariation'],
-
- 'version': ['parseDescription']
- };
- TagParser.prototype.parse = function parse() {
- var i, iz, sequences, method;
-
- if (!this._title) {
- if (!this.addError('Missing or invalid title')) {
- return null;
- }
- }
-
- this._last = seekContent(this._title);
- if (this._options.range) {
- this._tag.range = [this._first, source.slice(0, this._last).replace(/\s*$/, '').length].map(convertIndex);
- }
- if (hasOwnProperty(Rules, this._title)) {
- sequences = Rules[this._title];
- } else {
-
- 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;
-
- if (!skipToTag()) {
- return null;
- }
-
- title = scanTitle();
-
- parser = new TagParser(options, title);
- tag = parser.parse();
-
- while (index < parser._last) {
- advance();
- }
- return tag;
- }
-
-
-
- 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;
- }
- originalSource = comment;
-
- 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
- };
- }());
|