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