1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | (function () {
|
9 | 'use strict';
|
10 |
|
11 | var typed,
|
12 | utility,
|
13 | jsdoc,
|
14 | esutils,
|
15 | hasOwnProperty;
|
16 |
|
17 | esutils = require('esutils');
|
18 | typed = require('./typed');
|
19 | utility = require('./utility');
|
20 |
|
21 | function sliceSource(source, index, last) {
|
22 | return source.slice(index, last);
|
23 | }
|
24 |
|
25 | hasOwnProperty = (function () {
|
26 | var func = Object.prototype.hasOwnProperty;
|
27 | return function hasOwnProperty(obj, name) {
|
28 | return func.call(obj, name);
|
29 | };
|
30 | }());
|
31 | function shallowCopy(obj) {
|
32 | var ret = {}, key;
|
33 | for (key in obj) {
|
34 | if (obj.hasOwnProperty(key)) {
|
35 | ret[key] = obj[key];
|
36 | }
|
37 | }
|
38 | return ret;
|
39 | }
|
40 |
|
41 | function isASCIIAlphanumeric(ch) {
|
42 | return (ch >= 0x61 && ch <= 0x7A ) ||
|
43 | (ch >= 0x41 && ch <= 0x5A ) ||
|
44 | (ch >= 0x30 && ch <= 0x39 );
|
45 | }
|
46 |
|
47 | function isParamTitle(title) {
|
48 | return title === 'param' || title === 'argument' || title === 'arg';
|
49 | }
|
50 |
|
51 | function isReturnTitle(title) {
|
52 | return title === 'return' || title === 'returns';
|
53 | }
|
54 |
|
55 | function isProperty(title) {
|
56 | return title === 'property' || title === 'prop';
|
57 | }
|
58 |
|
59 | function isNameParameterRequired(title) {
|
60 | return isParamTitle(title) || isProperty(title) ||
|
61 | title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires';
|
62 | }
|
63 |
|
64 | function isAllowedName(title) {
|
65 | return isNameParameterRequired(title) || title === 'const' || title === 'constant';
|
66 | }
|
67 |
|
68 | function isAllowedNested(title) {
|
69 | return isProperty(title) || isParamTitle(title);
|
70 | }
|
71 |
|
72 | function isAllowedOptional(title) {
|
73 | return isProperty(title) || isParamTitle(title);
|
74 | }
|
75 |
|
76 | function isTypeParameterRequired(title) {
|
77 | return isParamTitle(title) || isReturnTitle(title) ||
|
78 | title === 'define' || title === 'enum' ||
|
79 | title === 'implements' || title === 'this' ||
|
80 | title === 'type' || title === 'typedef' || isProperty(title);
|
81 | }
|
82 |
|
83 |
|
84 |
|
85 | function isAllowedType(title) {
|
86 | return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' ||
|
87 | title === 'namespace' || title === 'member' || title === 'var' || title === 'module' ||
|
88 | title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' ||
|
89 | title === 'public' || title === 'private' || title === 'protected';
|
90 | }
|
91 |
|
92 |
|
93 | var WHITESPACE = '[ \\f\\t\\v\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]';
|
94 |
|
95 | var STAR_MATCHER = '(' + WHITESPACE + '*(?:\\*' + WHITESPACE + '?)?)(.+|[\r\n\u2028\u2029])';
|
96 |
|
97 | function unwrapComment(doc) {
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | return doc.
|
104 |
|
105 | replace(/^\/\*\*?/, '').
|
106 |
|
107 | replace(/\*\/$/, '').
|
108 |
|
109 | replace(new RegExp(STAR_MATCHER, 'g'), '$2').
|
110 |
|
111 | replace(/\s*$/, '');
|
112 | }
|
113 |
|
114 | |
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 | function convertUnwrappedCommentIndex(originalSource, unwrappedIndex) {
|
121 | var replacedSource = originalSource.replace(/^\/\*\*?/, '');
|
122 | var numSkippedChars = 0;
|
123 | var matcher = new RegExp(STAR_MATCHER, 'g');
|
124 | var match;
|
125 |
|
126 | while ((match = matcher.exec(replacedSource))) {
|
127 | numSkippedChars += match[1].length;
|
128 |
|
129 | if (match.index + match[0].length > unwrappedIndex + numSkippedChars) {
|
130 | return unwrappedIndex + numSkippedChars + originalSource.length - replacedSource.length;
|
131 | }
|
132 | }
|
133 |
|
134 | return originalSource.replace(/\*\/$/, '').replace(/\s*$/, '').length;
|
135 | }
|
136 |
|
137 |
|
138 |
|
139 | (function (exports) {
|
140 | var Rules,
|
141 | index,
|
142 | lineNumber,
|
143 | length,
|
144 | source,
|
145 | originalSource,
|
146 | recoverable,
|
147 | sloppy,
|
148 | strict;
|
149 |
|
150 | function advance() {
|
151 | var ch = source.charCodeAt(index);
|
152 | index += 1;
|
153 | if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D && source.charCodeAt(index) === 0x0A )) {
|
154 | lineNumber += 1;
|
155 | }
|
156 | return String.fromCharCode(ch);
|
157 | }
|
158 |
|
159 | function scanTitle() {
|
160 | var title = '';
|
161 |
|
162 | advance();
|
163 |
|
164 | while (index < length && isASCIIAlphanumeric(source.charCodeAt(index))) {
|
165 | title += advance();
|
166 | }
|
167 |
|
168 | return title;
|
169 | }
|
170 |
|
171 | function seekContent() {
|
172 | var ch, waiting, last = index;
|
173 |
|
174 | waiting = false;
|
175 | while (last < length) {
|
176 | ch = source.charCodeAt(last);
|
177 | if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D && source.charCodeAt(last + 1) === 0x0A )) {
|
178 | waiting = true;
|
179 | } else if (waiting) {
|
180 | if (ch === 0x40 ) {
|
181 | break;
|
182 | }
|
183 | if (!esutils.code.isWhiteSpace(ch)) {
|
184 | waiting = false;
|
185 | }
|
186 | }
|
187 | last += 1;
|
188 | }
|
189 | return last;
|
190 | }
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 | function parseType(title, last, addRange) {
|
197 | var ch, brace, type, startIndex, direct = false;
|
198 |
|
199 |
|
200 |
|
201 | while (index < last) {
|
202 | ch = source.charCodeAt(index);
|
203 | if (esutils.code.isWhiteSpace(ch)) {
|
204 | advance();
|
205 | } else if (ch === 0x7B ) {
|
206 | advance();
|
207 | break;
|
208 | } else {
|
209 |
|
210 | direct = true;
|
211 | break;
|
212 | }
|
213 | }
|
214 |
|
215 |
|
216 | if (direct) {
|
217 | return null;
|
218 | }
|
219 |
|
220 |
|
221 | brace = 1;
|
222 | type = '';
|
223 | while (index < last) {
|
224 | ch = source.charCodeAt(index);
|
225 | if (esutils.code.isLineTerminator(ch)) {
|
226 | advance();
|
227 | } else {
|
228 | if (ch === 0x7D ) {
|
229 | brace -= 1;
|
230 | if (brace === 0) {
|
231 | advance();
|
232 | break;
|
233 | }
|
234 | } else if (ch === 0x7B ) {
|
235 | brace += 1;
|
236 | }
|
237 | if (type === '') {
|
238 | startIndex = index;
|
239 | }
|
240 | type += advance();
|
241 | }
|
242 | }
|
243 |
|
244 | if (brace !== 0) {
|
245 |
|
246 | return utility.throwError('Braces are not balanced');
|
247 | }
|
248 |
|
249 | if (isAllowedOptional(title)) {
|
250 | return typed.parseParamType(type, {startIndex: convertIndex(startIndex), range: addRange});
|
251 | }
|
252 |
|
253 | return typed.parseType(type, {startIndex: convertIndex(startIndex), range: addRange});
|
254 | }
|
255 |
|
256 | function scanIdentifier(last) {
|
257 | var identifier;
|
258 | if (!esutils.code.isIdentifierStartES5(source.charCodeAt(index)) && !source[index].match(/[0-9]/)) {
|
259 | return null;
|
260 | }
|
261 | identifier = advance();
|
262 | while (index < last && esutils.code.isIdentifierPartES5(source.charCodeAt(index))) {
|
263 | identifier += advance();
|
264 | }
|
265 | return identifier;
|
266 | }
|
267 |
|
268 | function skipWhiteSpace(last) {
|
269 | while (index < last && (esutils.code.isWhiteSpace(source.charCodeAt(index)) || esutils.code.isLineTerminator(source.charCodeAt(index)))) {
|
270 | advance();
|
271 | }
|
272 | }
|
273 |
|
274 | function parseName(last, allowBrackets, allowNestedParams) {
|
275 | var name = '',
|
276 | useBrackets,
|
277 | insideString;
|
278 |
|
279 |
|
280 | skipWhiteSpace(last);
|
281 |
|
282 | if (index >= last) {
|
283 | return null;
|
284 | }
|
285 |
|
286 | if (source.charCodeAt(index) === 0x5B ) {
|
287 | if (allowBrackets) {
|
288 | useBrackets = true;
|
289 | name = advance();
|
290 | } else {
|
291 | return null;
|
292 | }
|
293 | }
|
294 |
|
295 | name += scanIdentifier(last);
|
296 |
|
297 | if (allowNestedParams) {
|
298 | if (source.charCodeAt(index) === 0x3A && (
|
299 | name === 'module' ||
|
300 | name === 'external' ||
|
301 | name === 'event')) {
|
302 | name += advance();
|
303 | name += scanIdentifier(last);
|
304 |
|
305 | }
|
306 | if(source.charCodeAt(index) === 0x5B && source.charCodeAt(index + 1) === 0x5D ){
|
307 | name += advance();
|
308 | name += advance();
|
309 | }
|
310 | while (source.charCodeAt(index) === 0x2E ||
|
311 | source.charCodeAt(index) === 0x2F ||
|
312 | source.charCodeAt(index) === 0x23 ||
|
313 | source.charCodeAt(index) === 0x2D ||
|
314 | source.charCodeAt(index) === 0x7E ) {
|
315 | name += advance();
|
316 | name += scanIdentifier(last);
|
317 | }
|
318 | }
|
319 |
|
320 | if (useBrackets) {
|
321 | skipWhiteSpace(last);
|
322 |
|
323 | if (source.charCodeAt(index) === 0x3D ) {
|
324 |
|
325 | name += advance();
|
326 | skipWhiteSpace(last);
|
327 |
|
328 | var ch;
|
329 | var bracketDepth = 1;
|
330 |
|
331 |
|
332 | while (index < last) {
|
333 | ch = source.charCodeAt(index);
|
334 |
|
335 | if (esutils.code.isWhiteSpace(ch)) {
|
336 | if (!insideString) {
|
337 | skipWhiteSpace(last);
|
338 | ch = source.charCodeAt(index);
|
339 | }
|
340 | }
|
341 |
|
342 | if (ch === 0x27 ) {
|
343 | if (!insideString) {
|
344 | insideString = '\'';
|
345 | } else {
|
346 | if (insideString === '\'') {
|
347 | insideString = '';
|
348 | }
|
349 | }
|
350 | }
|
351 |
|
352 | if (ch === 0x22 ) {
|
353 | if (!insideString) {
|
354 | insideString = '"';
|
355 | } else {
|
356 | if (insideString === '"') {
|
357 | insideString = '';
|
358 | }
|
359 | }
|
360 | }
|
361 |
|
362 | if (ch === 0x5B ) {
|
363 | bracketDepth++;
|
364 | } else if (ch === 0x5D &&
|
365 | --bracketDepth === 0) {
|
366 | break;
|
367 | }
|
368 |
|
369 | name += advance();
|
370 | }
|
371 | }
|
372 |
|
373 | skipWhiteSpace(last);
|
374 |
|
375 | if (index >= last || source.charCodeAt(index) !== 0x5D ) {
|
376 |
|
377 | return null;
|
378 | }
|
379 |
|
380 |
|
381 | name += advance();
|
382 | }
|
383 |
|
384 | return name;
|
385 | }
|
386 |
|
387 | function skipToTag() {
|
388 | while (index < length && source.charCodeAt(index) !== 0x40 ) {
|
389 | advance();
|
390 | }
|
391 | if (index >= length) {
|
392 | return false;
|
393 | }
|
394 | utility.assert(source.charCodeAt(index) === 0x40 );
|
395 | return true;
|
396 | }
|
397 |
|
398 | function convertIndex(rangeIndex) {
|
399 | if (source === originalSource) {
|
400 | return rangeIndex;
|
401 | }
|
402 | return convertUnwrappedCommentIndex(originalSource, rangeIndex);
|
403 | }
|
404 |
|
405 | function TagParser(options, title) {
|
406 | this._options = options;
|
407 | this._title = title.toLowerCase();
|
408 | this._tag = {
|
409 | title: title,
|
410 | description: null
|
411 | };
|
412 | if (this._options.lineNumbers) {
|
413 | this._tag.lineNumber = lineNumber;
|
414 | }
|
415 | this._first = index - title.length - 1;
|
416 | this._last = 0;
|
417 |
|
418 | this._extra = { };
|
419 | }
|
420 |
|
421 |
|
422 | TagParser.prototype.addError = function addError(errorText) {
|
423 | var args = Array.prototype.slice.call(arguments, 1),
|
424 | msg = errorText.replace(
|
425 | /%(\d)/g,
|
426 | function (whole, index) {
|
427 | utility.assert(index < args.length, 'Message reference must be in range');
|
428 | return args[index];
|
429 | }
|
430 | );
|
431 |
|
432 | if (!this._tag.errors) {
|
433 | this._tag.errors = [];
|
434 | }
|
435 | if (strict) {
|
436 | utility.throwError(msg);
|
437 | }
|
438 | this._tag.errors.push(msg);
|
439 | return recoverable;
|
440 | };
|
441 |
|
442 | TagParser.prototype.parseType = function () {
|
443 |
|
444 | if (isTypeParameterRequired(this._title)) {
|
445 | try {
|
446 | this._tag.type = parseType(this._title, this._last, this._options.range);
|
447 | if (!this._tag.type) {
|
448 | if (!isParamTitle(this._title) && !isReturnTitle(this._title)) {
|
449 | if (!this.addError('Missing or invalid tag type')) {
|
450 | return false;
|
451 | }
|
452 | }
|
453 | }
|
454 | } catch (error) {
|
455 | this._tag.type = null;
|
456 | if (!this.addError(error.message)) {
|
457 | return false;
|
458 | }
|
459 | }
|
460 | } else if (isAllowedType(this._title)) {
|
461 |
|
462 | try {
|
463 | this._tag.type = parseType(this._title, this._last, this._options.range);
|
464 | } catch (e) {
|
465 |
|
466 | }
|
467 | }
|
468 | return true;
|
469 | };
|
470 |
|
471 | TagParser.prototype._parseNamePath = function (optional) {
|
472 | var name;
|
473 | name = parseName(this._last, sloppy && isAllowedOptional(this._title), true);
|
474 | if (!name) {
|
475 | if (!optional) {
|
476 | if (!this.addError('Missing or invalid tag name')) {
|
477 | return false;
|
478 | }
|
479 | }
|
480 | }
|
481 | this._tag.name = name;
|
482 | return true;
|
483 | };
|
484 |
|
485 | TagParser.prototype.parseNamePath = function () {
|
486 | return this._parseNamePath(false);
|
487 | };
|
488 |
|
489 | TagParser.prototype.parseNamePathOptional = function () {
|
490 | return this._parseNamePath(true);
|
491 | };
|
492 |
|
493 |
|
494 | TagParser.prototype.parseName = function () {
|
495 | var assign, name;
|
496 |
|
497 |
|
498 | if (isAllowedName(this._title)) {
|
499 | this._tag.name = parseName(this._last, sloppy && isAllowedOptional(this._title), isAllowedNested(this._title));
|
500 | if (!this._tag.name) {
|
501 | if (!isNameParameterRequired(this._title)) {
|
502 | return true;
|
503 | }
|
504 |
|
505 |
|
506 |
|
507 |
|
508 | if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) {
|
509 | this._extra.name = this._tag.type;
|
510 | this._tag.name = this._tag.type.name;
|
511 | this._tag.type = null;
|
512 | } else {
|
513 | if (!this.addError('Missing or invalid tag name')) {
|
514 | return false;
|
515 | }
|
516 | }
|
517 | } else {
|
518 | name = this._tag.name;
|
519 | if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') {
|
520 |
|
521 |
|
522 | assign = name.substring(1, name.length - 1).split('=');
|
523 | if (assign.length > 1) {
|
524 | this._tag['default'] = assign.slice(1).join('=');
|
525 | }
|
526 | this._tag.name = assign[0];
|
527 |
|
528 |
|
529 | if (this._tag.type && this._tag.type.type !== 'OptionalType') {
|
530 | this._tag.type = {
|
531 | type: 'OptionalType',
|
532 | expression: this._tag.type
|
533 | };
|
534 | }
|
535 | }
|
536 | }
|
537 | }
|
538 |
|
539 |
|
540 | return true;
|
541 | };
|
542 |
|
543 | TagParser.prototype.parseDescription = function parseDescription() {
|
544 | var description = sliceSource(source, index, this._last).trim();
|
545 | if (description) {
|
546 | if ((/^-\s+/).test(description)) {
|
547 | description = description.substring(2);
|
548 | }
|
549 | this._tag.description = description;
|
550 | }
|
551 | return true;
|
552 | };
|
553 |
|
554 | TagParser.prototype.parseCaption = function parseDescription() {
|
555 | var description = sliceSource(source, index, this._last).trim();
|
556 | var captionStartTag = '<caption>';
|
557 | var captionEndTag = '</caption>';
|
558 | var captionStart = description.indexOf(captionStartTag);
|
559 | var captionEnd = description.indexOf(captionEndTag);
|
560 | if (captionStart >= 0 && captionEnd >= 0) {
|
561 | this._tag.caption = description.substring(
|
562 | captionStart + captionStartTag.length, captionEnd).trim();
|
563 | this._tag.description = description.substring(captionEnd + captionEndTag.length).trim();
|
564 | } else {
|
565 | this._tag.description = description;
|
566 | }
|
567 | return true;
|
568 | };
|
569 |
|
570 | TagParser.prototype.parseKind = function parseKind() {
|
571 | var kind, kinds;
|
572 | kinds = {
|
573 | 'class': true,
|
574 | 'constant': true,
|
575 | 'event': true,
|
576 | 'external': true,
|
577 | 'file': true,
|
578 | 'function': true,
|
579 | 'member': true,
|
580 | 'mixin': true,
|
581 | 'module': true,
|
582 | 'namespace': true,
|
583 | 'typedef': true
|
584 | };
|
585 | kind = sliceSource(source, index, this._last).trim();
|
586 | this._tag.kind = kind;
|
587 | if (!hasOwnProperty(kinds, kind)) {
|
588 | if (!this.addError('Invalid kind name \'%0\'', kind)) {
|
589 | return false;
|
590 | }
|
591 | }
|
592 | return true;
|
593 | };
|
594 |
|
595 | TagParser.prototype.parseAccess = function parseAccess() {
|
596 | var access;
|
597 | access = sliceSource(source, index, this._last).trim();
|
598 | this._tag.access = access;
|
599 | if (access !== 'private' && access !== 'protected' && access !== 'public') {
|
600 | if (!this.addError('Invalid access name \'%0\'', access)) {
|
601 | return false;
|
602 | }
|
603 | }
|
604 | return true;
|
605 | };
|
606 |
|
607 | TagParser.prototype.parseThis = function parseThis() {
|
608 |
|
609 |
|
610 | var value = sliceSource(source, index, this._last).trim();
|
611 | if (value && value.charAt(0) === '{') {
|
612 | var gotType = this.parseType();
|
613 | if (gotType && this._tag.type.type === 'NameExpression' || this._tag.type.type === 'UnionType') {
|
614 | this._tag.name = this._tag.type.name;
|
615 | return true;
|
616 | } else {
|
617 | return this.addError('Invalid name for this');
|
618 | }
|
619 | } else {
|
620 | return this.parseNamePath();
|
621 | }
|
622 | };
|
623 |
|
624 | TagParser.prototype.parseVariation = function parseVariation() {
|
625 | var variation, text;
|
626 | text = sliceSource(source, index, this._last).trim();
|
627 | variation = parseFloat(text, 10);
|
628 | this._tag.variation = variation;
|
629 | if (isNaN(variation)) {
|
630 | if (!this.addError('Invalid variation \'%0\'', text)) {
|
631 | return false;
|
632 | }
|
633 | }
|
634 | return true;
|
635 | };
|
636 |
|
637 | TagParser.prototype.ensureEnd = function () {
|
638 | var shouldBeEmpty = sliceSource(source, index, this._last).trim();
|
639 | if (shouldBeEmpty) {
|
640 | if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) {
|
641 | return false;
|
642 | }
|
643 | }
|
644 | return true;
|
645 | };
|
646 |
|
647 | TagParser.prototype.epilogue = function epilogue() {
|
648 | var description;
|
649 |
|
650 | description = this._tag.description;
|
651 |
|
652 | if (isAllowedOptional(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
|
653 | this._tag.type = this._extra.name;
|
654 | if (!this._tag.name) {
|
655 | this._tag.name = undefined;
|
656 | }
|
657 |
|
658 | if (!sloppy) {
|
659 | if (!this.addError('Missing or invalid tag name')) {
|
660 | return false;
|
661 | }
|
662 | }
|
663 | }
|
664 |
|
665 | return true;
|
666 | };
|
667 |
|
668 | Rules = {
|
669 |
|
670 | 'access': ['parseAccess'],
|
671 |
|
672 | 'alias': ['parseNamePath', 'ensureEnd'],
|
673 |
|
674 | 'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
675 |
|
676 | 'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
677 |
|
678 | 'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
679 |
|
680 | 'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
681 |
|
682 | 'example': ['parseCaption'],
|
683 |
|
684 | 'deprecated': ['parseDescription'],
|
685 |
|
686 | 'global': ['ensureEnd'],
|
687 |
|
688 | 'inner': ['ensureEnd'],
|
689 |
|
690 | 'instance': ['ensureEnd'],
|
691 |
|
692 | 'kind': ['parseKind'],
|
693 |
|
694 | 'mixes': ['parseNamePath', 'ensureEnd'],
|
695 |
|
696 | 'mixin': ['parseNamePathOptional', 'ensureEnd'],
|
697 |
|
698 | 'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
699 |
|
700 | 'method': ['parseNamePathOptional', 'ensureEnd'],
|
701 |
|
702 | 'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
703 |
|
704 | 'func': ['parseNamePathOptional', 'ensureEnd'],
|
705 |
|
706 | 'function': ['parseNamePathOptional', 'ensureEnd'],
|
707 |
|
708 | 'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
709 |
|
710 | 'name': ['parseNamePath', 'ensureEnd'],
|
711 |
|
712 | 'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
713 |
|
714 | 'private': ['parseType', 'parseDescription'],
|
715 |
|
716 | 'protected': ['parseType', 'parseDescription'],
|
717 |
|
718 | 'public': ['parseType', 'parseDescription'],
|
719 |
|
720 | 'readonly': ['ensureEnd'],
|
721 |
|
722 | 'requires': ['parseNamePath', 'ensureEnd'],
|
723 |
|
724 | 'since': ['parseDescription'],
|
725 |
|
726 | 'static': ['ensureEnd'],
|
727 |
|
728 | 'summary': ['parseDescription'],
|
729 |
|
730 | 'this': ['parseThis', 'ensureEnd'],
|
731 |
|
732 | 'todo': ['parseDescription'],
|
733 |
|
734 | 'typedef': ['parseType', 'parseNamePathOptional'],
|
735 |
|
736 | 'variation': ['parseVariation'],
|
737 |
|
738 | 'version': ['parseDescription']
|
739 | };
|
740 |
|
741 | TagParser.prototype.parse = function parse() {
|
742 | var i, iz, sequences, method;
|
743 |
|
744 |
|
745 |
|
746 | if (!this._title) {
|
747 | if (!this.addError('Missing or invalid title')) {
|
748 | return null;
|
749 | }
|
750 | }
|
751 |
|
752 |
|
753 | this._last = seekContent(this._title);
|
754 |
|
755 | if (this._options.range) {
|
756 | this._tag.range = [this._first, source.slice(0, this._last).replace(/\s*$/, '').length].map(convertIndex);
|
757 | }
|
758 |
|
759 | if (hasOwnProperty(Rules, this._title)) {
|
760 | sequences = Rules[this._title];
|
761 | } else {
|
762 |
|
763 | sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue'];
|
764 | }
|
765 |
|
766 | for (i = 0, iz = sequences.length; i < iz; ++i) {
|
767 | method = sequences[i];
|
768 | if (!this[method]()) {
|
769 | return null;
|
770 | }
|
771 | }
|
772 |
|
773 | return this._tag;
|
774 | };
|
775 |
|
776 | function parseTag(options) {
|
777 | var title, parser, tag;
|
778 |
|
779 |
|
780 | if (!skipToTag()) {
|
781 | return null;
|
782 | }
|
783 |
|
784 |
|
785 | title = scanTitle();
|
786 |
|
787 |
|
788 | parser = new TagParser(options, title);
|
789 | tag = parser.parse();
|
790 |
|
791 |
|
792 | while (index < parser._last) {
|
793 | advance();
|
794 | }
|
795 |
|
796 | return tag;
|
797 | }
|
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 | function scanJSDocDescription(preserveWhitespace) {
|
804 | var description = '', ch, atAllowed;
|
805 |
|
806 | atAllowed = true;
|
807 | while (index < length) {
|
808 | ch = source.charCodeAt(index);
|
809 |
|
810 | if (atAllowed && ch === 0x40 ) {
|
811 | break;
|
812 | }
|
813 |
|
814 | if (esutils.code.isLineTerminator(ch)) {
|
815 | atAllowed = true;
|
816 | } else if (atAllowed && !esutils.code.isWhiteSpace(ch)) {
|
817 | atAllowed = false;
|
818 | }
|
819 |
|
820 | description += advance();
|
821 | }
|
822 |
|
823 | return preserveWhitespace ? description : description.trim();
|
824 | }
|
825 |
|
826 | function parse(comment, options) {
|
827 | var tags = [], tag, description, interestingTags, i, iz;
|
828 |
|
829 | if (options === undefined) {
|
830 | options = {};
|
831 | }
|
832 |
|
833 | if (typeof options.unwrap === 'boolean' && options.unwrap) {
|
834 | source = unwrapComment(comment);
|
835 | } else {
|
836 | source = comment;
|
837 | }
|
838 |
|
839 | originalSource = comment;
|
840 |
|
841 |
|
842 | if (options.tags) {
|
843 | if (Array.isArray(options.tags)) {
|
844 | interestingTags = { };
|
845 | for (i = 0, iz = options.tags.length; i < iz; i++) {
|
846 | if (typeof options.tags[i] === 'string') {
|
847 | interestingTags[options.tags[i]] = true;
|
848 | } else {
|
849 | utility.throwError('Invalid "tags" parameter: ' + options.tags);
|
850 | }
|
851 | }
|
852 | } else {
|
853 | utility.throwError('Invalid "tags" parameter: ' + options.tags);
|
854 | }
|
855 | }
|
856 |
|
857 | length = source.length;
|
858 | index = 0;
|
859 | lineNumber = 0;
|
860 | recoverable = options.recoverable;
|
861 | sloppy = options.sloppy;
|
862 | strict = options.strict;
|
863 |
|
864 | description = scanJSDocDescription(options.preserveWhitespace);
|
865 |
|
866 | while (true) {
|
867 | tag = parseTag(options);
|
868 | if (!tag) {
|
869 | break;
|
870 | }
|
871 | if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
|
872 | tags.push(tag);
|
873 | }
|
874 | }
|
875 |
|
876 | return {
|
877 | description: description,
|
878 | tags: tags
|
879 | };
|
880 | }
|
881 | exports.parse = parse;
|
882 | }(jsdoc = {}));
|
883 |
|
884 | exports.version = utility.VERSION;
|
885 | exports.parse = jsdoc.parse;
|
886 | exports.parseType = typed.parseType;
|
887 | exports.parseParamType = typed.parseParamType;
|
888 | exports.unwrapComment = unwrapComment;
|
889 | exports.Syntax = shallowCopy(typed.Syntax);
|
890 | exports.Error = utility.DoctrineError;
|
891 | exports.type = {
|
892 | Syntax: exports.Syntax,
|
893 | parseType: typed.parseType,
|
894 | parseParamType: typed.parseParamType,
|
895 | stringify: typed.stringify
|
896 | };
|
897 | }());
|
898 |
|