1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | (function () {
|
28 | 'use strict';
|
29 |
|
30 | var VERSION,
|
31 | typed,
|
32 | jsdoc,
|
33 | esutils,
|
34 | isArray,
|
35 | hasOwnProperty;
|
36 |
|
37 |
|
38 | VERSION = require('./package.json').version;
|
39 |
|
40 | esutils = require('esutils');
|
41 |
|
42 | function sliceSource(source, index, last) {
|
43 | return source.slice(index, last);
|
44 | }
|
45 |
|
46 | isArray = Array.isArray;
|
47 | if (!isArray) {
|
48 | isArray = function isArray(ary) {
|
49 | return Object.prototype.toString.call(ary) === '[object Array]';
|
50 | };
|
51 | }
|
52 |
|
53 | hasOwnProperty = (function () {
|
54 | var func = Object.prototype.hasOwnProperty;
|
55 | return function hasOwnProperty(obj, name) {
|
56 | return func.call(obj, name);
|
57 | };
|
58 | }());
|
59 |
|
60 | function shallowCopy(obj) {
|
61 | var ret = {}, key;
|
62 | for (key in obj) {
|
63 | if (obj.hasOwnProperty(key)) {
|
64 | ret[key] = obj[key];
|
65 | }
|
66 | }
|
67 | return ret;
|
68 | }
|
69 |
|
70 | function isASCIIAlphanumeric(ch) {
|
71 | return (ch >= 0x61 && ch <= 0x7A ) ||
|
72 | (ch >= 0x41 && ch <= 0x5A ) ||
|
73 | (ch >= 0x30 && ch <= 0x39 );
|
74 | }
|
75 |
|
76 | function isTypeName(ch) {
|
77 | return '><(){}[],:*|?!='.indexOf(String.fromCharCode(ch)) === -1 && !esutils.code.isWhiteSpace(ch) && !esutils.code.isLineTerminator(ch);
|
78 | }
|
79 |
|
80 | function isParamTitle(title) {
|
81 | return title === 'param' || title === 'argument' || title === 'arg';
|
82 | }
|
83 |
|
84 | function isProperty(title) {
|
85 | return title === 'property' || title === 'prop';
|
86 | }
|
87 |
|
88 | function isNameParameterRequired(title) {
|
89 | return isParamTitle(title) || isProperty(title) ||
|
90 | title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires';
|
91 | }
|
92 |
|
93 | function isAllowedName(title) {
|
94 | return isNameParameterRequired(title) || title === 'const' || title === 'constant';
|
95 | }
|
96 |
|
97 | function isAllowedNested(title) {
|
98 | return isProperty(title) || isParamTitle(title);
|
99 | }
|
100 |
|
101 | function isTypeParameterRequired(title) {
|
102 | return isParamTitle(title) || title === 'define' || title === 'enum' ||
|
103 | title === 'implements' || title === 'return' ||
|
104 | title === 'this' || title === 'type' || title === 'typedef' ||
|
105 | title === 'returns' || isProperty(title);
|
106 | }
|
107 |
|
108 |
|
109 |
|
110 | function isAllowedType(title) {
|
111 | return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' ||
|
112 | title === 'namespace' || title === 'member' || title === 'var' || title === 'module' ||
|
113 | title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' ||
|
114 | title === 'public' || title === 'private' || title === 'protected';
|
115 | }
|
116 |
|
117 | function DoctrineError(message) {
|
118 | this.name = 'DoctrineError';
|
119 | this.message = message;
|
120 | }
|
121 | DoctrineError.prototype = (function () {
|
122 | var Middle = function () { };
|
123 | Middle.prototype = Error.prototype;
|
124 | return new Middle();
|
125 | }());
|
126 | DoctrineError.prototype.constructor = DoctrineError;
|
127 |
|
128 | function throwError(message) {
|
129 | throw new DoctrineError(message);
|
130 | }
|
131 |
|
132 | function assert(cond, text) {
|
133 | if (VERSION.slice(-3) === 'dev') {
|
134 | if (!cond) {
|
135 | throwError(text);
|
136 | }
|
137 | }
|
138 | }
|
139 |
|
140 | function trim(str) {
|
141 | return str.replace(/^\s+/, '').replace(/\s+$/, '');
|
142 | }
|
143 |
|
144 | function unwrapComment(doc) {
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 | var BEFORE_STAR = 0,
|
151 | STAR = 1,
|
152 | AFTER_STAR = 2,
|
153 | index,
|
154 | len,
|
155 | mode,
|
156 | result,
|
157 | ch;
|
158 |
|
159 | doc = doc.replace(/^\/\*\*?/, '').replace(/\*\/$/, '');
|
160 | index = 0;
|
161 | len = doc.length;
|
162 | mode = BEFORE_STAR;
|
163 | result = '';
|
164 |
|
165 | while (index < len) {
|
166 | ch = doc.charCodeAt(index);
|
167 | switch (mode) {
|
168 | case BEFORE_STAR:
|
169 | if (esutils.code.isLineTerminator(ch)) {
|
170 | result += String.fromCharCode(ch);
|
171 | } else if (ch === 0x2A ) {
|
172 | mode = STAR;
|
173 | } else if (!esutils.code.isWhiteSpace(ch)) {
|
174 | result += String.fromCharCode(ch);
|
175 | mode = AFTER_STAR;
|
176 | }
|
177 | break;
|
178 |
|
179 | case STAR:
|
180 | if (!esutils.code.isWhiteSpace(ch)) {
|
181 | result += String.fromCharCode(ch);
|
182 | }
|
183 | mode = esutils.code.isLineTerminator(ch) ? BEFORE_STAR : AFTER_STAR;
|
184 | break;
|
185 |
|
186 | case AFTER_STAR:
|
187 | result += String.fromCharCode(ch);
|
188 | if (esutils.code.isLineTerminator(ch)) {
|
189 | mode = BEFORE_STAR;
|
190 | }
|
191 | break;
|
192 | }
|
193 | index += 1;
|
194 | }
|
195 |
|
196 | return result;
|
197 | }
|
198 |
|
199 |
|
200 |
|
201 | (function (exports) {
|
202 | var Syntax,
|
203 | Token,
|
204 | source,
|
205 | length,
|
206 | index,
|
207 | previous,
|
208 | token,
|
209 | value;
|
210 |
|
211 | Syntax = {
|
212 | NullableLiteral: 'NullableLiteral',
|
213 | AllLiteral: 'AllLiteral',
|
214 | NullLiteral: 'NullLiteral',
|
215 | UndefinedLiteral: 'UndefinedLiteral',
|
216 | VoidLiteral: 'VoidLiteral',
|
217 | UnionType: 'UnionType',
|
218 | ArrayType: 'ArrayType',
|
219 | RecordType: 'RecordType',
|
220 | FieldType: 'FieldType',
|
221 | FunctionType: 'FunctionType',
|
222 | ParameterType: 'ParameterType',
|
223 | RestType: 'RestType',
|
224 | NonNullableType: 'NonNullableType',
|
225 | OptionalType: 'OptionalType',
|
226 | NullableType: 'NullableType',
|
227 | NameExpression: 'NameExpression',
|
228 | TypeApplication: 'TypeApplication'
|
229 | };
|
230 |
|
231 | Token = {
|
232 | ILLEGAL: 0,
|
233 | DOT_LT: 1,
|
234 | REST: 2,
|
235 | LT: 3,
|
236 | GT: 4,
|
237 | LPAREN: 5,
|
238 | RPAREN: 6,
|
239 | LBRACE: 7,
|
240 | RBRACE: 8,
|
241 | LBRACK: 9,
|
242 | RBRACK: 10,
|
243 | COMMA: 11,
|
244 | COLON: 12,
|
245 | STAR: 13,
|
246 | PIPE: 14,
|
247 | QUESTION: 15,
|
248 | BANG: 16,
|
249 | EQUAL: 17,
|
250 | NAME: 18,
|
251 | STRING: 19,
|
252 | NUMBER: 20,
|
253 | EOF: 21
|
254 | };
|
255 |
|
256 | function Context(previous, index, token, value) {
|
257 | this._previous = previous;
|
258 | this._index = index;
|
259 | this._token = token;
|
260 | this._value = value;
|
261 | }
|
262 |
|
263 | Context.prototype.restore = function () {
|
264 | previous = this._previous;
|
265 | index = this._index;
|
266 | token = this._token;
|
267 | value = this._value;
|
268 | };
|
269 |
|
270 | Context.save = function () {
|
271 | return new Context(previous, index, token, value);
|
272 | };
|
273 |
|
274 | function advance() {
|
275 | var ch = source.charAt(index);
|
276 | index += 1;
|
277 | return ch;
|
278 | }
|
279 |
|
280 | function scanHexEscape(prefix) {
|
281 | var i, len, ch, code = 0;
|
282 |
|
283 | len = (prefix === 'u') ? 4 : 2;
|
284 | for (i = 0; i < len; ++i) {
|
285 | if (index < length && esutils.code.isHexDigit(source.charCodeAt(index))) {
|
286 | ch = advance();
|
287 | code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
|
288 | } else {
|
289 | return '';
|
290 | }
|
291 | }
|
292 | return String.fromCharCode(code);
|
293 | }
|
294 |
|
295 | function scanString() {
|
296 | var str = '', quote, ch, code, unescaped, restore;
|
297 | quote = source.charAt(index);
|
298 | ++index;
|
299 |
|
300 | while (index < length) {
|
301 | ch = advance();
|
302 |
|
303 | if (ch === quote) {
|
304 | quote = '';
|
305 | break;
|
306 | } else if (ch === '\\') {
|
307 | ch = advance();
|
308 | if (!esutils.code.isLineTerminator(ch.charCodeAt(0))) {
|
309 | switch (ch) {
|
310 | case 'n':
|
311 | str += '\n';
|
312 | break;
|
313 | case 'r':
|
314 | str += '\r';
|
315 | break;
|
316 | case 't':
|
317 | str += '\t';
|
318 | break;
|
319 | case 'u':
|
320 | case 'x':
|
321 | restore = index;
|
322 | unescaped = scanHexEscape(ch);
|
323 | if (unescaped) {
|
324 | str += unescaped;
|
325 | } else {
|
326 | index = restore;
|
327 | str += ch;
|
328 | }
|
329 | break;
|
330 | case 'b':
|
331 | str += '\b';
|
332 | break;
|
333 | case 'f':
|
334 | str += '\f';
|
335 | break;
|
336 | case 'v':
|
337 | str += '\v';
|
338 | break;
|
339 |
|
340 | default:
|
341 | if (esutils.code.isOctalDigit(ch.charCodeAt(0))) {
|
342 | code = '01234567'.indexOf(ch);
|
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 |
|
349 |
|
350 | if (index < length && esutils.code.isOctalDigit(source.charCodeAt(index))) {
|
351 |
|
352 | code = code * 8 + '01234567'.indexOf(advance());
|
353 |
|
354 |
|
355 |
|
356 | if ('0123'.indexOf(ch) >= 0 &&
|
357 | index < length &&
|
358 | esutils.code.isOctalDigit(source.charCodeAt(index))) {
|
359 | code = code * 8 + '01234567'.indexOf(advance());
|
360 | }
|
361 | }
|
362 | str += String.fromCharCode(code);
|
363 | } else {
|
364 | str += ch;
|
365 | }
|
366 | break;
|
367 | }
|
368 | } else {
|
369 | if (ch === '\r' && source.charCodeAt(index) === 0x0A ) {
|
370 | ++index;
|
371 | }
|
372 | }
|
373 | } else if (esutils.code.isLineTerminator(ch.charCodeAt(0))) {
|
374 | break;
|
375 | } else {
|
376 | str += ch;
|
377 | }
|
378 | }
|
379 |
|
380 | if (quote !== '') {
|
381 | throwError('unexpected quote');
|
382 | }
|
383 |
|
384 | value = str;
|
385 | return Token.STRING;
|
386 | }
|
387 |
|
388 | function scanNumber() {
|
389 | var number, ch;
|
390 |
|
391 | number = '';
|
392 | ch = source.charCodeAt(index);
|
393 |
|
394 | if (ch !== 0x2E ) {
|
395 | number = advance();
|
396 | ch = source.charCodeAt(index);
|
397 |
|
398 | if (number === '0') {
|
399 | if (ch === 0x78 || ch === 0x58 ) {
|
400 | number += advance();
|
401 | while (index < length) {
|
402 | ch = source.charCodeAt(index);
|
403 | if (!esutils.code.isHexDigit(ch)) {
|
404 | break;
|
405 | }
|
406 | number += advance();
|
407 | }
|
408 |
|
409 | if (number.length <= 2) {
|
410 |
|
411 | throwError('unexpected token');
|
412 | }
|
413 |
|
414 | if (index < length) {
|
415 | ch = source.charCodeAt(index);
|
416 | if (esutils.code.isIdentifierStart(ch)) {
|
417 | throwError('unexpected token');
|
418 | }
|
419 | }
|
420 | value = parseInt(number, 16);
|
421 | return Token.NUMBER;
|
422 | }
|
423 |
|
424 | if (esutils.code.isOctalDigit(ch)) {
|
425 | number += advance();
|
426 | while (index < length) {
|
427 | ch = source.charCodeAt(index);
|
428 | if (!esutils.code.isOctalDigit(ch)) {
|
429 | break;
|
430 | }
|
431 | number += advance();
|
432 | }
|
433 |
|
434 | if (index < length) {
|
435 | ch = source.charCodeAt(index);
|
436 | if (esutils.code.isIdentifierStart(ch) || esutils.code.isDecimalDigit(ch)) {
|
437 | throwError('unexpected token');
|
438 | }
|
439 | }
|
440 | value = parseInt(number, 8);
|
441 | return Token.NUMBER;
|
442 | }
|
443 |
|
444 | if (esutils.code.isDecimalDigit(ch)) {
|
445 | throwError('unexpected token');
|
446 | }
|
447 | }
|
448 |
|
449 | while (index < length) {
|
450 | ch = source.charCodeAt(index);
|
451 | if (!esutils.code.isDecimalDigit(ch)) {
|
452 | break;
|
453 | }
|
454 | number += advance();
|
455 | }
|
456 | }
|
457 |
|
458 | if (ch === 0x2E ) {
|
459 | number += advance();
|
460 | while (index < length) {
|
461 | ch = source.charCodeAt(index);
|
462 | if (!esutils.code.isDecimalDigit(ch)) {
|
463 | break;
|
464 | }
|
465 | number += advance();
|
466 | }
|
467 | }
|
468 |
|
469 | if (ch === 0x65 || ch === 0x45 ) {
|
470 | number += advance();
|
471 |
|
472 | ch = source.charCodeAt(index);
|
473 | if (ch === 0x2B || ch === 0x2D ) {
|
474 | number += advance();
|
475 | }
|
476 |
|
477 | ch = source.charCodeAt(index);
|
478 | if (esutils.code.isDecimalDigit(ch)) {
|
479 | number += advance();
|
480 | while (index < length) {
|
481 | ch = source.charCodeAt(index);
|
482 | if (!esutils.code.isDecimalDigit(ch)) {
|
483 | break;
|
484 | }
|
485 | number += advance();
|
486 | }
|
487 | } else {
|
488 | throwError('unexpected token');
|
489 | }
|
490 | }
|
491 |
|
492 | if (index < length) {
|
493 | ch = source.charCodeAt(index);
|
494 | if (esutils.code.isIdentifierStart(ch)) {
|
495 | throwError('unexpected token');
|
496 | }
|
497 | }
|
498 |
|
499 | value = parseFloat(number);
|
500 | return Token.NUMBER;
|
501 | }
|
502 |
|
503 |
|
504 | function scanTypeName() {
|
505 | var ch, ch2;
|
506 |
|
507 | value = advance();
|
508 | while (index < length && isTypeName(source.charCodeAt(index))) {
|
509 | ch = source.charCodeAt(index);
|
510 | if (ch === 0x2E ) {
|
511 | if ((index + 1) >= length) {
|
512 | return Token.ILLEGAL;
|
513 | }
|
514 | ch2 = source.charCodeAt(index + 1);
|
515 | if (ch2 === 0x3C ) {
|
516 | break;
|
517 | }
|
518 | }
|
519 | value += advance();
|
520 | }
|
521 | return Token.NAME;
|
522 | }
|
523 |
|
524 | function next() {
|
525 | var ch;
|
526 |
|
527 | previous = index;
|
528 |
|
529 | while (index < length && esutils.code.isWhiteSpace(source.charCodeAt(index))) {
|
530 | advance();
|
531 | }
|
532 | if (index >= length) {
|
533 | token = Token.EOF;
|
534 | return token;
|
535 | }
|
536 |
|
537 | ch = source.charCodeAt(index);
|
538 | switch (ch) {
|
539 | case 0x27:
|
540 | case 0x22:
|
541 | token = scanString();
|
542 | return token;
|
543 |
|
544 | case 0x3A:
|
545 | advance();
|
546 | token = Token.COLON;
|
547 | return token;
|
548 |
|
549 | case 0x2C:
|
550 | advance();
|
551 | token = Token.COMMA;
|
552 | return token;
|
553 |
|
554 | case 0x28:
|
555 | advance();
|
556 | token = Token.LPAREN;
|
557 | return token;
|
558 |
|
559 | case 0x29:
|
560 | advance();
|
561 | token = Token.RPAREN;
|
562 | return token;
|
563 |
|
564 | case 0x5B:
|
565 | advance();
|
566 | token = Token.LBRACK;
|
567 | return token;
|
568 |
|
569 | case 0x5D:
|
570 | advance();
|
571 | token = Token.RBRACK;
|
572 | return token;
|
573 |
|
574 | case 0x7B:
|
575 | advance();
|
576 | token = Token.LBRACE;
|
577 | return token;
|
578 |
|
579 | case 0x7D:
|
580 | advance();
|
581 | token = Token.RBRACE;
|
582 | return token;
|
583 |
|
584 | case 0x2E:
|
585 | if (index + 1 < length) {
|
586 | ch = source.charCodeAt(index + 1);
|
587 | if (ch === 0x3C ) {
|
588 | advance();
|
589 | advance();
|
590 | token = Token.DOT_LT;
|
591 | return token;
|
592 | }
|
593 |
|
594 | if (ch === 0x2E && index + 2 < length && source.charCodeAt(index + 2) === 0x2E ) {
|
595 | advance();
|
596 | advance();
|
597 | advance();
|
598 | token = Token.REST;
|
599 | return token;
|
600 | }
|
601 |
|
602 | if (esutils.code.isDecimalDigit(ch)) {
|
603 | token = scanNumber();
|
604 | return token;
|
605 | }
|
606 | }
|
607 | token = Token.ILLEGAL;
|
608 | return token;
|
609 |
|
610 | case 0x3C:
|
611 | advance();
|
612 | token = Token.LT;
|
613 | return token;
|
614 |
|
615 | case 0x3E:
|
616 | advance();
|
617 | token = Token.GT;
|
618 | return token;
|
619 |
|
620 | case 0x2A:
|
621 | advance();
|
622 | token = Token.STAR;
|
623 | return token;
|
624 |
|
625 | case 0x7C:
|
626 | advance();
|
627 | token = Token.PIPE;
|
628 | return token;
|
629 |
|
630 | case 0x3F:
|
631 | advance();
|
632 | token = Token.QUESTION;
|
633 | return token;
|
634 |
|
635 | case 0x21:
|
636 | advance();
|
637 | token = Token.BANG;
|
638 | return token;
|
639 |
|
640 | case 0x3D:
|
641 | advance();
|
642 | token = Token.EQUAL;
|
643 | return token;
|
644 |
|
645 | default:
|
646 | if (esutils.code.isDecimalDigit(ch)) {
|
647 | token = scanNumber();
|
648 | return token;
|
649 | }
|
650 |
|
651 |
|
652 |
|
653 |
|
654 |
|
655 |
|
656 | assert(isTypeName(ch));
|
657 | token = scanTypeName();
|
658 | return token;
|
659 | }
|
660 | }
|
661 |
|
662 | function consume(target, text) {
|
663 | assert(token === target, text || 'consumed token not matched');
|
664 | next();
|
665 | }
|
666 |
|
667 | function expect(target) {
|
668 | if (token !== target) {
|
669 | throwError('unexpected token');
|
670 | }
|
671 | next();
|
672 | }
|
673 |
|
674 |
|
675 |
|
676 |
|
677 |
|
678 |
|
679 |
|
680 |
|
681 |
|
682 |
|
683 | function parseUnionType() {
|
684 | var elements;
|
685 | consume(Token.LPAREN, 'UnionType should start with (');
|
686 | elements = [];
|
687 | if (token !== Token.RPAREN) {
|
688 | while (true) {
|
689 | elements.push(parseTypeExpression());
|
690 | if (token === Token.RPAREN) {
|
691 | break;
|
692 | }
|
693 | expect(Token.PIPE);
|
694 | }
|
695 | }
|
696 | consume(Token.RPAREN, 'UnionType should end with )');
|
697 | return {
|
698 | type: Syntax.UnionType,
|
699 | elements: elements
|
700 | };
|
701 | }
|
702 |
|
703 |
|
704 |
|
705 |
|
706 |
|
707 |
|
708 |
|
709 |
|
710 | function parseArrayType() {
|
711 | var elements;
|
712 | consume(Token.LBRACK, 'ArrayType should start with [');
|
713 | elements = [];
|
714 | while (token !== Token.RBRACK) {
|
715 | if (token === Token.REST) {
|
716 | consume(Token.REST);
|
717 | elements.push({
|
718 | type: Syntax.RestType,
|
719 | expression: parseTypeExpression()
|
720 | });
|
721 | break;
|
722 | } else {
|
723 | elements.push(parseTypeExpression());
|
724 | }
|
725 | if (token !== Token.RBRACK) {
|
726 | expect(Token.COMMA);
|
727 | }
|
728 | }
|
729 | expect(Token.RBRACK);
|
730 | return {
|
731 | type: Syntax.ArrayType,
|
732 | elements: elements
|
733 | };
|
734 | }
|
735 |
|
736 | function parseFieldName() {
|
737 | var v = value;
|
738 | if (token === Token.NAME || token === Token.STRING) {
|
739 | next();
|
740 | return v;
|
741 | }
|
742 |
|
743 | if (token === Token.NUMBER) {
|
744 | consume(Token.NUMBER);
|
745 | return String(v);
|
746 | }
|
747 |
|
748 | throwError('unexpected token');
|
749 | }
|
750 |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 | function parseFieldType() {
|
761 | var key;
|
762 |
|
763 | key = parseFieldName();
|
764 | if (token === Token.COLON) {
|
765 | consume(Token.COLON);
|
766 | return {
|
767 | type: Syntax.FieldType,
|
768 | key: key,
|
769 | value: parseTypeExpression()
|
770 | };
|
771 | }
|
772 | return {
|
773 | type: Syntax.FieldType,
|
774 | key: key,
|
775 | value: null
|
776 | };
|
777 | }
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 | function parseRecordType() {
|
786 | var fields;
|
787 |
|
788 | consume(Token.LBRACE, 'RecordType should start with {');
|
789 | fields = [];
|
790 | if (token === Token.COMMA) {
|
791 | consume(Token.COMMA);
|
792 | } else {
|
793 | while (token !== Token.RBRACE) {
|
794 | fields.push(parseFieldType());
|
795 | if (token !== Token.RBRACE) {
|
796 | expect(Token.COMMA);
|
797 | }
|
798 | }
|
799 | }
|
800 | expect(Token.RBRACE);
|
801 | return {
|
802 | type: Syntax.RecordType,
|
803 | fields: fields
|
804 | };
|
805 | }
|
806 |
|
807 | function parseNameExpression() {
|
808 | var name = value;
|
809 | expect(Token.NAME);
|
810 | return {
|
811 | type: Syntax.NameExpression,
|
812 | name: name
|
813 | };
|
814 | }
|
815 |
|
816 |
|
817 |
|
818 |
|
819 | function parseTypeExpressionList() {
|
820 | var elements = [];
|
821 |
|
822 | elements.push(parseTop());
|
823 | while (token === Token.COMMA) {
|
824 | consume(Token.COMMA);
|
825 | elements.push(parseTop());
|
826 | }
|
827 | return elements;
|
828 | }
|
829 |
|
830 |
|
831 |
|
832 |
|
833 |
|
834 |
|
835 |
|
836 |
|
837 | function parseTypeName() {
|
838 | var expr, applications;
|
839 |
|
840 | expr = parseNameExpression();
|
841 | if (token === Token.DOT_LT || token === Token.LT) {
|
842 | next();
|
843 | applications = parseTypeExpressionList();
|
844 | expect(Token.GT);
|
845 | return {
|
846 | type: Syntax.TypeApplication,
|
847 | expression: expr,
|
848 | applications: applications
|
849 | };
|
850 | }
|
851 | return expr;
|
852 | }
|
853 |
|
854 |
|
855 |
|
856 |
|
857 |
|
858 |
|
859 |
|
860 |
|
861 | function parseResultType() {
|
862 | consume(Token.COLON, 'ResultType should start with :');
|
863 | if (token === Token.NAME && value === 'void') {
|
864 | consume(Token.NAME);
|
865 | return {
|
866 | type: Syntax.VoidLiteral
|
867 | };
|
868 | }
|
869 | return parseTypeExpression();
|
870 | }
|
871 |
|
872 |
|
873 |
|
874 |
|
875 |
|
876 |
|
877 |
|
878 |
|
879 |
|
880 |
|
881 |
|
882 |
|
883 |
|
884 |
|
885 |
|
886 |
|
887 |
|
888 |
|
889 |
|
890 |
|
891 |
|
892 |
|
893 |
|
894 |
|
895 | function parseParametersType() {
|
896 | var params = [], optionalSequence = false, expr, rest = false;
|
897 |
|
898 | while (token !== Token.RPAREN) {
|
899 | if (token === Token.REST) {
|
900 |
|
901 | consume(Token.REST);
|
902 | rest = true;
|
903 | }
|
904 |
|
905 | expr = parseTypeExpression();
|
906 | if (expr.type === Syntax.NameExpression && token === Token.COLON) {
|
907 |
|
908 | consume(Token.COLON);
|
909 | expr = {
|
910 | type: Syntax.ParameterType,
|
911 | name: expr.name,
|
912 | expression: parseTypeExpression()
|
913 | };
|
914 | }
|
915 | if (token === Token.EQUAL) {
|
916 | consume(Token.EQUAL);
|
917 | expr = {
|
918 | type: Syntax.OptionalType,
|
919 | expression: expr
|
920 | };
|
921 | optionalSequence = true;
|
922 | } else {
|
923 | if (optionalSequence) {
|
924 | throwError('unexpected token');
|
925 | }
|
926 | }
|
927 | if (rest) {
|
928 | expr = {
|
929 | type: Syntax.RestType,
|
930 | expression: expr
|
931 | };
|
932 | }
|
933 | params.push(expr);
|
934 | if (token !== Token.RPAREN) {
|
935 | expect(Token.COMMA);
|
936 | }
|
937 | }
|
938 | return params;
|
939 | }
|
940 |
|
941 |
|
942 |
|
943 |
|
944 |
|
945 |
|
946 |
|
947 |
|
948 | function parseFunctionType() {
|
949 | var isNew, thisBinding, params, result, fnType;
|
950 | assert(token === Token.NAME && value === 'function', 'FunctionType should start with \'function\'');
|
951 | consume(Token.NAME);
|
952 |
|
953 |
|
954 |
|
955 | expect(Token.LPAREN);
|
956 |
|
957 | isNew = false;
|
958 | params = [];
|
959 | thisBinding = null;
|
960 | if (token !== Token.RPAREN) {
|
961 |
|
962 | if (token === Token.NAME &&
|
963 | (value === 'this' || value === 'new')) {
|
964 |
|
965 |
|
966 | isNew = value === 'new';
|
967 | consume(Token.NAME);
|
968 | expect(Token.COLON);
|
969 | thisBinding = parseTypeName();
|
970 | if (token === Token.COMMA) {
|
971 | consume(Token.COMMA);
|
972 | params = parseParametersType();
|
973 | }
|
974 | } else {
|
975 | params = parseParametersType();
|
976 | }
|
977 | }
|
978 |
|
979 | expect(Token.RPAREN);
|
980 |
|
981 | result = null;
|
982 | if (token === Token.COLON) {
|
983 | result = parseResultType();
|
984 | }
|
985 |
|
986 | fnType = {
|
987 | type: Syntax.FunctionType,
|
988 | params: params,
|
989 | result: result
|
990 | };
|
991 | if (thisBinding) {
|
992 |
|
993 | fnType['this'] = thisBinding;
|
994 | if (isNew) {
|
995 | fnType['new'] = true;
|
996 | }
|
997 | }
|
998 | return fnType;
|
999 | }
|
1000 |
|
1001 |
|
1002 |
|
1003 |
|
1004 |
|
1005 |
|
1006 |
|
1007 |
|
1008 |
|
1009 |
|
1010 | function parseBasicTypeExpression() {
|
1011 | var context;
|
1012 | switch (token) {
|
1013 | case Token.STAR:
|
1014 | consume(Token.STAR);
|
1015 | return {
|
1016 | type: Syntax.AllLiteral
|
1017 | };
|
1018 |
|
1019 | case Token.LPAREN:
|
1020 | return parseUnionType();
|
1021 |
|
1022 | case Token.LBRACK:
|
1023 | return parseArrayType();
|
1024 |
|
1025 | case Token.LBRACE:
|
1026 | return parseRecordType();
|
1027 |
|
1028 | case Token.NAME:
|
1029 | if (value === 'null') {
|
1030 | consume(Token.NAME);
|
1031 | return {
|
1032 | type: Syntax.NullLiteral
|
1033 | };
|
1034 | }
|
1035 |
|
1036 | if (value === 'undefined') {
|
1037 | consume(Token.NAME);
|
1038 | return {
|
1039 | type: Syntax.UndefinedLiteral
|
1040 | };
|
1041 | }
|
1042 |
|
1043 | context = Context.save();
|
1044 | if (value === 'function') {
|
1045 | try {
|
1046 | return parseFunctionType();
|
1047 | } catch (e) {
|
1048 | context.restore();
|
1049 | }
|
1050 | }
|
1051 |
|
1052 | return parseTypeName();
|
1053 |
|
1054 | default:
|
1055 | throwError('unexpected token');
|
1056 | }
|
1057 | }
|
1058 |
|
1059 |
|
1060 |
|
1061 |
|
1062 |
|
1063 |
|
1064 |
|
1065 |
|
1066 |
|
1067 | function parseTypeExpression() {
|
1068 | var expr;
|
1069 |
|
1070 | if (token === Token.QUESTION) {
|
1071 | consume(Token.QUESTION);
|
1072 | if (token === Token.COMMA || token === Token.EQUAL || token === Token.RBRACE ||
|
1073 | token === Token.RPAREN || token === Token.PIPE || token === Token.EOF ||
|
1074 | token === Token.RBRACK) {
|
1075 | return {
|
1076 | type: Syntax.NullableLiteral
|
1077 | };
|
1078 | }
|
1079 | return {
|
1080 | type: Syntax.NullableType,
|
1081 | expression: parseBasicTypeExpression(),
|
1082 | prefix: true
|
1083 | };
|
1084 | }
|
1085 |
|
1086 | if (token === Token.BANG) {
|
1087 | consume(Token.BANG);
|
1088 | return {
|
1089 | type: Syntax.NonNullableType,
|
1090 | expression: parseBasicTypeExpression(),
|
1091 | prefix: true
|
1092 | };
|
1093 | }
|
1094 |
|
1095 | expr = parseBasicTypeExpression();
|
1096 | if (token === Token.BANG) {
|
1097 | consume(Token.BANG);
|
1098 | return {
|
1099 | type: Syntax.NonNullableType,
|
1100 | expression: expr,
|
1101 | prefix: false
|
1102 | };
|
1103 | }
|
1104 |
|
1105 | if (token === Token.QUESTION) {
|
1106 | consume(Token.QUESTION);
|
1107 | return {
|
1108 | type: Syntax.NullableType,
|
1109 | expression: expr,
|
1110 | prefix: false
|
1111 | };
|
1112 | }
|
1113 |
|
1114 | if (token === Token.LBRACK) {
|
1115 | consume(Token.LBRACK);
|
1116 | consume(Token.RBRACK, 'expected an array-style type declaration (' + value + '[])');
|
1117 | return {
|
1118 | type: Syntax.TypeApplication,
|
1119 | expression: {
|
1120 | type: Syntax.NameExpression,
|
1121 | name: 'Array'
|
1122 | },
|
1123 | applications: [expr]
|
1124 | };
|
1125 | }
|
1126 |
|
1127 | return expr;
|
1128 | }
|
1129 |
|
1130 |
|
1131 |
|
1132 |
|
1133 |
|
1134 |
|
1135 |
|
1136 |
|
1137 |
|
1138 |
|
1139 | function parseTop() {
|
1140 | var expr, elements;
|
1141 |
|
1142 | expr = parseTypeExpression();
|
1143 | if (token !== Token.PIPE) {
|
1144 | return expr;
|
1145 | }
|
1146 |
|
1147 | elements = [ expr ];
|
1148 | consume(Token.PIPE);
|
1149 | while (true) {
|
1150 | elements.push(parseTypeExpression());
|
1151 | if (token !== Token.PIPE) {
|
1152 | break;
|
1153 | }
|
1154 | consume(Token.PIPE);
|
1155 | }
|
1156 |
|
1157 | return {
|
1158 | type: Syntax.UnionType,
|
1159 | elements: elements
|
1160 | };
|
1161 | }
|
1162 |
|
1163 | function parseTopParamType() {
|
1164 | var expr;
|
1165 |
|
1166 | if (token === Token.REST) {
|
1167 | consume(Token.REST);
|
1168 | return {
|
1169 | type: Syntax.RestType,
|
1170 | expression: parseTop()
|
1171 | };
|
1172 | }
|
1173 |
|
1174 | expr = parseTop();
|
1175 | if (token === Token.EQUAL) {
|
1176 | consume(Token.EQUAL);
|
1177 | return {
|
1178 | type: Syntax.OptionalType,
|
1179 | expression: expr
|
1180 | };
|
1181 | }
|
1182 |
|
1183 | return expr;
|
1184 | }
|
1185 |
|
1186 | function parseType(src, opt) {
|
1187 | var expr;
|
1188 |
|
1189 | source = src;
|
1190 | length = source.length;
|
1191 | index = 0;
|
1192 | previous = 0;
|
1193 |
|
1194 | next();
|
1195 | expr = parseTop();
|
1196 |
|
1197 | if (opt && opt.midstream) {
|
1198 | return {
|
1199 | expression: expr,
|
1200 | index: previous
|
1201 | };
|
1202 | }
|
1203 |
|
1204 | if (token !== Token.EOF) {
|
1205 | throwError('not reach to EOF');
|
1206 | }
|
1207 |
|
1208 | return expr;
|
1209 | }
|
1210 |
|
1211 | function parseParamType(src, opt) {
|
1212 | var expr;
|
1213 |
|
1214 | source = src;
|
1215 | length = source.length;
|
1216 | index = 0;
|
1217 | previous = 0;
|
1218 |
|
1219 | next();
|
1220 | expr = parseTopParamType();
|
1221 |
|
1222 | if (opt && opt.midstream) {
|
1223 | return {
|
1224 | expression: expr,
|
1225 | index: previous
|
1226 | };
|
1227 | }
|
1228 |
|
1229 | if (token !== Token.EOF) {
|
1230 | throwError('not reach to EOF');
|
1231 | }
|
1232 |
|
1233 | return expr;
|
1234 | }
|
1235 |
|
1236 | function stringifyImpl(node, compact, topLevel) {
|
1237 | var result, i, iz;
|
1238 |
|
1239 | switch (node.type) {
|
1240 | case Syntax.NullableLiteral:
|
1241 | result = '?';
|
1242 | break;
|
1243 |
|
1244 | case Syntax.AllLiteral:
|
1245 | result = '*';
|
1246 | break;
|
1247 |
|
1248 | case Syntax.NullLiteral:
|
1249 | result = 'null';
|
1250 | break;
|
1251 |
|
1252 | case Syntax.UndefinedLiteral:
|
1253 | result = 'undefined';
|
1254 | break;
|
1255 |
|
1256 | case Syntax.VoidLiteral:
|
1257 | result = 'void';
|
1258 | break;
|
1259 |
|
1260 | case Syntax.UnionType:
|
1261 | if (!topLevel) {
|
1262 | result = '(';
|
1263 | } else {
|
1264 | result = '';
|
1265 | }
|
1266 |
|
1267 | for (i = 0, iz = node.elements.length; i < iz; ++i) {
|
1268 | result += stringifyImpl(node.elements[i], compact);
|
1269 | if ((i + 1) !== iz) {
|
1270 | result += '|';
|
1271 | }
|
1272 | }
|
1273 |
|
1274 | if (!topLevel) {
|
1275 | result += ')';
|
1276 | }
|
1277 | break;
|
1278 |
|
1279 | case Syntax.ArrayType:
|
1280 | result = '[';
|
1281 | for (i = 0, iz = node.elements.length; i < iz; ++i) {
|
1282 | result += stringifyImpl(node.elements[i], compact);
|
1283 | if ((i + 1) !== iz) {
|
1284 | result += compact ? ',' : ', ';
|
1285 | }
|
1286 | }
|
1287 | result += ']';
|
1288 | break;
|
1289 |
|
1290 | case Syntax.RecordType:
|
1291 | result = '{';
|
1292 | for (i = 0, iz = node.fields.length; i < iz; ++i) {
|
1293 | result += stringifyImpl(node.fields[i], compact);
|
1294 | if ((i + 1) !== iz) {
|
1295 | result += compact ? ',' : ', ';
|
1296 | }
|
1297 | }
|
1298 | result += '}';
|
1299 | break;
|
1300 |
|
1301 | case Syntax.FieldType:
|
1302 | if (node.value) {
|
1303 | result = node.key + (compact ? ':' : ': ') + stringifyImpl(node.value, compact);
|
1304 | } else {
|
1305 | result = node.key;
|
1306 | }
|
1307 | break;
|
1308 |
|
1309 | case Syntax.FunctionType:
|
1310 | result = compact ? 'function(' : 'function (';
|
1311 |
|
1312 | if (node['this']) {
|
1313 | if (node['new']) {
|
1314 | result += (compact ? 'new:' : 'new: ');
|
1315 | } else {
|
1316 | result += (compact ? 'this:' : 'this: ');
|
1317 | }
|
1318 |
|
1319 | result += stringifyImpl(node['this'], compact);
|
1320 |
|
1321 | if (node.params.length !== 0) {
|
1322 | result += compact ? ',' : ', ';
|
1323 | }
|
1324 | }
|
1325 |
|
1326 | for (i = 0, iz = node.params.length; i < iz; ++i) {
|
1327 | result += stringifyImpl(node.params[i], compact);
|
1328 | if ((i + 1) !== iz) {
|
1329 | result += compact ? ',' : ', ';
|
1330 | }
|
1331 | }
|
1332 |
|
1333 | result += ')';
|
1334 |
|
1335 | if (node.result) {
|
1336 | result += (compact ? ':' : ': ') + stringifyImpl(node.result, compact);
|
1337 | }
|
1338 | break;
|
1339 |
|
1340 | case Syntax.ParameterType:
|
1341 | result = node.name + (compact ? ':' : ': ') + stringifyImpl(node.expression, compact);
|
1342 | break;
|
1343 |
|
1344 | case Syntax.RestType:
|
1345 | result = '...';
|
1346 | if (node.expression) {
|
1347 | result += stringifyImpl(node.expression, compact);
|
1348 | }
|
1349 | break;
|
1350 |
|
1351 | case Syntax.NonNullableType:
|
1352 | if (node.prefix) {
|
1353 | result = '!' + stringifyImpl(node.expression, compact);
|
1354 | } else {
|
1355 | result = stringifyImpl(node.expression, compact) + '!';
|
1356 | }
|
1357 | break;
|
1358 |
|
1359 | case Syntax.OptionalType:
|
1360 | result = stringifyImpl(node.expression, compact) + '=';
|
1361 | break;
|
1362 |
|
1363 | case Syntax.NullableType:
|
1364 | if (node.prefix) {
|
1365 | result = '?' + stringifyImpl(node.expression, compact);
|
1366 | } else {
|
1367 | result = stringifyImpl(node.expression, compact) + '?';
|
1368 | }
|
1369 | break;
|
1370 |
|
1371 | case Syntax.NameExpression:
|
1372 | result = node.name;
|
1373 | break;
|
1374 |
|
1375 | case Syntax.TypeApplication:
|
1376 | result = stringifyImpl(node.expression, compact) + '.<';
|
1377 | for (i = 0, iz = node.applications.length; i < iz; ++i) {
|
1378 | result += stringifyImpl(node.applications[i], compact);
|
1379 | if ((i + 1) !== iz) {
|
1380 | result += compact ? ',' : ', ';
|
1381 | }
|
1382 | }
|
1383 | result += '>';
|
1384 | break;
|
1385 |
|
1386 | default:
|
1387 | throwError('Unknown type ' + node.type);
|
1388 | }
|
1389 |
|
1390 | return result;
|
1391 | }
|
1392 |
|
1393 | function stringify(node, options) {
|
1394 | if (options == null) {
|
1395 | options = {};
|
1396 | }
|
1397 | return stringifyImpl(node, options.compact, options.topLevel);
|
1398 | }
|
1399 |
|
1400 | exports.parseType = parseType;
|
1401 | exports.parseParamType = parseParamType;
|
1402 | exports.stringify = stringify;
|
1403 | exports.Syntax = Syntax;
|
1404 | }(typed = {}));
|
1405 |
|
1406 |
|
1407 |
|
1408 | (function (exports) {
|
1409 | var Rules,
|
1410 | index,
|
1411 | lineNumber,
|
1412 | length,
|
1413 | source,
|
1414 | recoverable,
|
1415 | sloppy,
|
1416 | strict;
|
1417 |
|
1418 | function advance() {
|
1419 | var ch = source.charCodeAt(index);
|
1420 | index += 1;
|
1421 | if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D && source.charCodeAt(index) === 0x0A )) {
|
1422 | lineNumber += 1;
|
1423 | }
|
1424 | return String.fromCharCode(ch);
|
1425 | }
|
1426 |
|
1427 | function scanTitle() {
|
1428 | var title = '';
|
1429 |
|
1430 | advance();
|
1431 |
|
1432 | while (index < length && isASCIIAlphanumeric(source.charCodeAt(index))) {
|
1433 | title += advance();
|
1434 | }
|
1435 |
|
1436 | return title;
|
1437 | }
|
1438 |
|
1439 | function seekContent() {
|
1440 | var ch, waiting, last = index;
|
1441 |
|
1442 | waiting = false;
|
1443 | while (last < length) {
|
1444 | ch = source.charCodeAt(last);
|
1445 | if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D && source.charCodeAt(last + 1) === 0x0A )) {
|
1446 | lineNumber += 1;
|
1447 | waiting = true;
|
1448 | } else if (waiting) {
|
1449 | if (ch === 0x40 ) {
|
1450 | break;
|
1451 | }
|
1452 | if (!esutils.code.isWhiteSpace(ch)) {
|
1453 | waiting = false;
|
1454 | }
|
1455 | }
|
1456 | last += 1;
|
1457 | }
|
1458 | return last;
|
1459 | }
|
1460 |
|
1461 |
|
1462 |
|
1463 |
|
1464 |
|
1465 | function parseType(title, last) {
|
1466 | var ch, brace, type, direct = false;
|
1467 |
|
1468 |
|
1469 |
|
1470 | while (index < last) {
|
1471 | ch = source.charCodeAt(index);
|
1472 | if (esutils.code.isWhiteSpace(ch)) {
|
1473 | advance();
|
1474 | } else if (ch === 0x7B ) {
|
1475 | advance();
|
1476 | break;
|
1477 | } else {
|
1478 |
|
1479 | direct = true;
|
1480 | break;
|
1481 | }
|
1482 | }
|
1483 |
|
1484 |
|
1485 | if (direct) {
|
1486 | return null;
|
1487 | }
|
1488 |
|
1489 |
|
1490 | brace = 1;
|
1491 | type = '';
|
1492 | while (index < last) {
|
1493 | ch = source.charCodeAt(index);
|
1494 | if (esutils.code.isLineTerminator(ch)) {
|
1495 | advance();
|
1496 | } else {
|
1497 | if (ch === 0x7D ) {
|
1498 | brace -= 1;
|
1499 | if (brace === 0) {
|
1500 | advance();
|
1501 | break;
|
1502 | }
|
1503 | } else if (ch === 0x7B ) {
|
1504 | brace += 1;
|
1505 | }
|
1506 | type += advance();
|
1507 | }
|
1508 | }
|
1509 |
|
1510 | if (brace !== 0) {
|
1511 |
|
1512 | return throwError('Braces are not balanced');
|
1513 | }
|
1514 |
|
1515 | if (isParamTitle(title)) {
|
1516 | return typed.parseParamType(type);
|
1517 | }
|
1518 | return typed.parseType(type);
|
1519 | }
|
1520 |
|
1521 | function scanIdentifier(last) {
|
1522 | var identifier;
|
1523 | if (!esutils.code.isIdentifierStart(source.charCodeAt(index))) {
|
1524 | return null;
|
1525 | }
|
1526 | identifier = advance();
|
1527 | while (index < last && esutils.code.isIdentifierPart(source.charCodeAt(index))) {
|
1528 | identifier += advance();
|
1529 | }
|
1530 | return identifier;
|
1531 | }
|
1532 |
|
1533 | function skipWhiteSpace(last) {
|
1534 | while (index < last && (esutils.code.isWhiteSpace(source.charCodeAt(index)) || esutils.code.isLineTerminator(source.charCodeAt(index)))) {
|
1535 | advance();
|
1536 | }
|
1537 | }
|
1538 |
|
1539 | function parseName(last, allowBrackets, allowNestedParams) {
|
1540 | var name = '', useBrackets;
|
1541 |
|
1542 | skipWhiteSpace(last);
|
1543 |
|
1544 | if (index >= last) {
|
1545 | return null;
|
1546 | }
|
1547 |
|
1548 | if (allowBrackets && source.charCodeAt(index) === 0x5B ) {
|
1549 | useBrackets = true;
|
1550 | name = advance();
|
1551 | }
|
1552 |
|
1553 | if (!esutils.code.isIdentifierStart(source.charCodeAt(index))) {
|
1554 | return null;
|
1555 | }
|
1556 |
|
1557 | name += scanIdentifier(last);
|
1558 |
|
1559 | if (allowNestedParams) {
|
1560 | while (source.charCodeAt(index) === 0x2E ||
|
1561 | source.charCodeAt(index) === 0x23 ||
|
1562 | source.charCodeAt(index) === 0x7E ) {
|
1563 | name += advance();
|
1564 | name += scanIdentifier(last);
|
1565 | }
|
1566 | }
|
1567 |
|
1568 | if (useBrackets) {
|
1569 |
|
1570 | if (source.charCodeAt(index) === 0x3D ) {
|
1571 |
|
1572 |
|
1573 | name += advance();
|
1574 |
|
1575 | while (index < last && source.charCodeAt(index) !== 0x5D ) {
|
1576 | name += advance();
|
1577 | }
|
1578 | }
|
1579 |
|
1580 | if (index >= last || source.charCodeAt(index) !== 0x5D ) {
|
1581 |
|
1582 | return null;
|
1583 | }
|
1584 |
|
1585 |
|
1586 | name += advance();
|
1587 | }
|
1588 |
|
1589 | return name;
|
1590 | }
|
1591 |
|
1592 | function skipToTag() {
|
1593 | while (index < length && source.charCodeAt(index) !== 0x40 ) {
|
1594 | advance();
|
1595 | }
|
1596 | if (index >= length) {
|
1597 | return false;
|
1598 | }
|
1599 | assert(source.charCodeAt(index) === 0x40 );
|
1600 | return true;
|
1601 | }
|
1602 |
|
1603 | function TagParser(options, title) {
|
1604 | this._options = options;
|
1605 | this._title = title;
|
1606 | this._tag = {
|
1607 | title: title,
|
1608 | description: null
|
1609 | };
|
1610 | if (this._options.lineNumbers) {
|
1611 | this._tag.lineNumber = lineNumber;
|
1612 | }
|
1613 | this._last = 0;
|
1614 |
|
1615 | this._extra = { };
|
1616 | }
|
1617 |
|
1618 |
|
1619 | TagParser.prototype.addError = function addError(errorText) {
|
1620 | var args = Array.prototype.slice.call(arguments, 1),
|
1621 | msg = errorText.replace(
|
1622 | /%(\d)/g,
|
1623 | function (whole, index) {
|
1624 | assert(index < args.length, 'Message reference must be in range');
|
1625 | return args[index];
|
1626 | }
|
1627 | );
|
1628 |
|
1629 | if (!this._tag.errors) {
|
1630 | this._tag.errors = [];
|
1631 | }
|
1632 | if (strict) {
|
1633 | throwError(msg);
|
1634 | }
|
1635 | this._tag.errors.push(msg);
|
1636 | return recoverable;
|
1637 | };
|
1638 |
|
1639 | TagParser.prototype.parseType = function () {
|
1640 |
|
1641 | if (isTypeParameterRequired(this._title)) {
|
1642 | try {
|
1643 | this._tag.type = parseType(this._title, this._last);
|
1644 | if (!this._tag.type) {
|
1645 | if (!isParamTitle(this._title)) {
|
1646 | if (!this.addError('Missing or invalid tag type')) {
|
1647 | return false;
|
1648 | }
|
1649 | }
|
1650 | }
|
1651 | } catch (error) {
|
1652 | this._tag.type = null;
|
1653 | if (!this.addError(error.message)) {
|
1654 | return false;
|
1655 | }
|
1656 | }
|
1657 | } else if (isAllowedType(this._title)) {
|
1658 |
|
1659 | try {
|
1660 | this._tag.type = parseType(this._title, this._last);
|
1661 | } catch (e) {
|
1662 |
|
1663 | }
|
1664 | }
|
1665 | return true;
|
1666 | };
|
1667 |
|
1668 | TagParser.prototype._parseNamePath = function (optional) {
|
1669 | var name;
|
1670 | name = parseName(this._last, sloppy && isParamTitle(this._title), true);
|
1671 | if (!name) {
|
1672 | if (!optional) {
|
1673 | if (!this.addError('Missing or invalid tag name')) {
|
1674 | return false;
|
1675 | }
|
1676 | }
|
1677 | }
|
1678 | this._tag.name = name;
|
1679 | return true;
|
1680 | };
|
1681 |
|
1682 | TagParser.prototype.parseNamePath = function () {
|
1683 | return this._parseNamePath(false);
|
1684 | };
|
1685 |
|
1686 | TagParser.prototype.parseNamePathOptional = function () {
|
1687 | return this._parseNamePath(true);
|
1688 | };
|
1689 |
|
1690 |
|
1691 | TagParser.prototype.parseName = function () {
|
1692 | var assign, name;
|
1693 |
|
1694 |
|
1695 | if (isAllowedName(this._title)) {
|
1696 | this._tag.name = parseName(this._last, sloppy && isParamTitle(this._title), isAllowedNested(this._title));
|
1697 | if (!this._tag.name) {
|
1698 | if (!isNameParameterRequired(this._title)) {
|
1699 | return true;
|
1700 | }
|
1701 |
|
1702 |
|
1703 |
|
1704 |
|
1705 | if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) {
|
1706 | this._extra.name = this._tag.type;
|
1707 | this._tag.name = this._tag.type.name;
|
1708 | this._tag.type = null;
|
1709 | } else {
|
1710 | if (!this.addError('Missing or invalid tag name')) {
|
1711 | return false;
|
1712 | }
|
1713 | }
|
1714 | } else {
|
1715 | name = this._tag.name;
|
1716 | if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') {
|
1717 |
|
1718 |
|
1719 | assign = name.substring(1, name.length - 1).split('=');
|
1720 | if (assign[1]) {
|
1721 | this._tag['default'] = assign[1];
|
1722 | }
|
1723 | this._tag.name = assign[0];
|
1724 |
|
1725 |
|
1726 | if (this._tag.type && this._tag.type.type !== 'OptionalType') {
|
1727 | this._tag.type = {
|
1728 | type: 'OptionalType',
|
1729 | expression: this._tag.type
|
1730 | };
|
1731 | }
|
1732 | }
|
1733 | }
|
1734 | }
|
1735 |
|
1736 | return true;
|
1737 | };
|
1738 |
|
1739 | TagParser.prototype.parseDescription = function parseDescription() {
|
1740 | var description = trim(sliceSource(source, index, this._last));
|
1741 | if (description) {
|
1742 | if ((/^-\s+/).test(description)) {
|
1743 | description = description.substring(2);
|
1744 | }
|
1745 | this._tag.description = description;
|
1746 | }
|
1747 | return true;
|
1748 | };
|
1749 |
|
1750 | TagParser.prototype.parseKind = function parseKind() {
|
1751 | var kind, kinds;
|
1752 | kinds = {
|
1753 | 'class': true,
|
1754 | 'constant': true,
|
1755 | 'event': true,
|
1756 | 'external': true,
|
1757 | 'file': true,
|
1758 | 'function': true,
|
1759 | 'member': true,
|
1760 | 'mixin': true,
|
1761 | 'module': true,
|
1762 | 'namespace': true,
|
1763 | 'typedef': true
|
1764 | };
|
1765 | kind = trim(sliceSource(source, index, this._last));
|
1766 | this._tag.kind = kind;
|
1767 | if (!hasOwnProperty(kinds, kind)) {
|
1768 | if (!this.addError('Invalid kind name \'%0\'', kind)) {
|
1769 | return false;
|
1770 | }
|
1771 | }
|
1772 | return true;
|
1773 | };
|
1774 |
|
1775 | TagParser.prototype.parseAccess = function parseAccess() {
|
1776 | var access;
|
1777 | access = trim(sliceSource(source, index, this._last));
|
1778 | this._tag.access = access;
|
1779 | if (access !== 'private' && access !== 'protected' && access !== 'public') {
|
1780 | if (!this.addError('Invalid access name \'%0\'', access)) {
|
1781 | return false;
|
1782 | }
|
1783 | }
|
1784 | return true;
|
1785 | };
|
1786 |
|
1787 | TagParser.prototype.parseVariation = function parseVariation() {
|
1788 | var variation, text;
|
1789 | text = trim(sliceSource(source, index, this._last));
|
1790 | variation = parseFloat(text, 10);
|
1791 | this._tag.variation = variation;
|
1792 | if (isNaN(variation)) {
|
1793 | if (!this.addError('Invalid variation \'%0\'', text)) {
|
1794 | return false;
|
1795 | }
|
1796 | }
|
1797 | return true;
|
1798 | };
|
1799 |
|
1800 | TagParser.prototype.ensureEnd = function () {
|
1801 | var shouldBeEmpty = trim(sliceSource(source, index, this._last));
|
1802 | if (shouldBeEmpty) {
|
1803 | if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) {
|
1804 | return false;
|
1805 | }
|
1806 | }
|
1807 | return true;
|
1808 | };
|
1809 |
|
1810 | TagParser.prototype.epilogue = function epilogue() {
|
1811 | var description;
|
1812 |
|
1813 | description = this._tag.description;
|
1814 |
|
1815 | if (isParamTitle(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
|
1816 | this._tag.type = this._extra.name;
|
1817 | this._tag.name = undefined;
|
1818 |
|
1819 | if (!sloppy) {
|
1820 | if (!this.addError('Missing or invalid tag name')) {
|
1821 | return false;
|
1822 | }
|
1823 | }
|
1824 | }
|
1825 |
|
1826 | return true;
|
1827 | };
|
1828 |
|
1829 | Rules = {
|
1830 |
|
1831 | 'access': ['parseAccess'],
|
1832 |
|
1833 | 'alias': ['parseNamePath', 'ensureEnd'],
|
1834 |
|
1835 | 'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1836 |
|
1837 | 'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1838 |
|
1839 | 'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1840 |
|
1841 | 'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1842 |
|
1843 | 'deprecated': ['parseDescription'],
|
1844 |
|
1845 | 'global': ['ensureEnd'],
|
1846 |
|
1847 | 'inner': ['ensureEnd'],
|
1848 |
|
1849 | 'instance': ['ensureEnd'],
|
1850 |
|
1851 | 'kind': ['parseKind'],
|
1852 |
|
1853 | 'mixes': ['parseNamePath', 'ensureEnd'],
|
1854 |
|
1855 | 'mixin': ['parseNamePathOptional', 'ensureEnd'],
|
1856 |
|
1857 | 'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1858 |
|
1859 | 'method': ['parseNamePathOptional', 'ensureEnd'],
|
1860 |
|
1861 | 'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1862 |
|
1863 | 'func': ['parseNamePathOptional', 'ensureEnd'],
|
1864 |
|
1865 | 'function': ['parseNamePathOptional', 'ensureEnd'],
|
1866 |
|
1867 | 'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1868 |
|
1869 | 'name': ['parseNamePath', 'ensureEnd'],
|
1870 |
|
1871 | 'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
|
1872 |
|
1873 | 'private': ['parseType', 'parseDescription'],
|
1874 |
|
1875 | 'protected': ['parseType', 'parseDescription'],
|
1876 |
|
1877 | 'public': ['parseType', 'parseDescription'],
|
1878 |
|
1879 | 'readonly': ['ensureEnd'],
|
1880 |
|
1881 | 'requires': ['parseNamePath', 'ensureEnd'],
|
1882 |
|
1883 | 'since': ['parseDescription'],
|
1884 |
|
1885 | 'static': ['ensureEnd'],
|
1886 |
|
1887 | 'summary': ['parseDescription'],
|
1888 |
|
1889 | 'this': ['parseNamePath', 'ensureEnd'],
|
1890 |
|
1891 | 'todo': ['parseDescription'],
|
1892 |
|
1893 | 'variation': ['parseVariation'],
|
1894 |
|
1895 | 'version': ['parseDescription']
|
1896 | };
|
1897 |
|
1898 | TagParser.prototype.parse = function parse() {
|
1899 | var i, iz, sequences, method;
|
1900 |
|
1901 |
|
1902 | if (!this._title) {
|
1903 | if (!this.addError('Missing or invalid title')) {
|
1904 | return null;
|
1905 | }
|
1906 | }
|
1907 |
|
1908 |
|
1909 | this._last = seekContent(this._title);
|
1910 |
|
1911 | if (hasOwnProperty(Rules, this._title)) {
|
1912 | sequences = Rules[this._title];
|
1913 | } else {
|
1914 |
|
1915 | sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue'];
|
1916 | }
|
1917 |
|
1918 | for (i = 0, iz = sequences.length; i < iz; ++i) {
|
1919 | method = sequences[i];
|
1920 | if (!this[method]()) {
|
1921 | return null;
|
1922 | }
|
1923 | }
|
1924 |
|
1925 |
|
1926 | index = this._last;
|
1927 | return this._tag;
|
1928 | };
|
1929 |
|
1930 | function parseTag(options) {
|
1931 | var title, parser;
|
1932 |
|
1933 |
|
1934 | if (!skipToTag()) {
|
1935 | return null;
|
1936 | }
|
1937 |
|
1938 |
|
1939 | title = scanTitle();
|
1940 |
|
1941 |
|
1942 | parser = new TagParser(options, title);
|
1943 | return parser.parse();
|
1944 | }
|
1945 |
|
1946 |
|
1947 |
|
1948 |
|
1949 |
|
1950 | function scanJSDocDescription() {
|
1951 | var description = '', ch, atAllowed;
|
1952 |
|
1953 | atAllowed = true;
|
1954 | while (index < length) {
|
1955 | ch = source.charCodeAt(index);
|
1956 |
|
1957 | if (atAllowed && ch === 0x40 ) {
|
1958 | break;
|
1959 | }
|
1960 |
|
1961 | if (esutils.code.isLineTerminator(ch)) {
|
1962 | atAllowed = true;
|
1963 | } else if (atAllowed && !esutils.code.isWhiteSpace(ch)) {
|
1964 | atAllowed = false;
|
1965 | }
|
1966 |
|
1967 | description += advance();
|
1968 | }
|
1969 | return trim(description);
|
1970 | }
|
1971 |
|
1972 | function parse(comment, options) {
|
1973 | var tags = [], tag, description, interestingTags, i, iz;
|
1974 |
|
1975 | if (options === undefined) {
|
1976 | options = {};
|
1977 | }
|
1978 |
|
1979 | if (typeof options.unwrap === 'boolean' && options.unwrap) {
|
1980 | source = unwrapComment(comment);
|
1981 | } else {
|
1982 | source = comment;
|
1983 | }
|
1984 |
|
1985 |
|
1986 | if (options.tags) {
|
1987 | if (isArray(options.tags)) {
|
1988 | interestingTags = { };
|
1989 | for (i = 0, iz = options.tags.length; i < iz; i++) {
|
1990 | if (typeof options.tags[i] === 'string') {
|
1991 | interestingTags[options.tags[i]] = true;
|
1992 | } else {
|
1993 | throwError('Invalid "tags" parameter: ' + options.tags);
|
1994 | }
|
1995 | }
|
1996 | } else {
|
1997 | throwError('Invalid "tags" parameter: ' + options.tags);
|
1998 | }
|
1999 | }
|
2000 |
|
2001 | length = source.length;
|
2002 | index = 0;
|
2003 | lineNumber = 0;
|
2004 | recoverable = options.recoverable;
|
2005 | sloppy = options.sloppy;
|
2006 | strict = options.strict;
|
2007 |
|
2008 | description = scanJSDocDescription();
|
2009 |
|
2010 | while (true) {
|
2011 | tag = parseTag(options);
|
2012 | if (!tag) {
|
2013 | break;
|
2014 | }
|
2015 | if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
|
2016 | tags.push(tag);
|
2017 | }
|
2018 | }
|
2019 |
|
2020 | return {
|
2021 | description: description,
|
2022 | tags: tags
|
2023 | };
|
2024 | }
|
2025 | exports.parse = parse;
|
2026 | }(jsdoc = {}));
|
2027 |
|
2028 | exports.version = VERSION;
|
2029 | exports.parse = jsdoc.parse;
|
2030 | exports.parseType = typed.parseType;
|
2031 | exports.parseParamType = typed.parseParamType;
|
2032 | exports.unwrapComment = unwrapComment;
|
2033 | exports.Syntax = shallowCopy(typed.Syntax);
|
2034 | exports.Error = DoctrineError;
|
2035 | exports.type = {
|
2036 | Syntax: exports.Syntax,
|
2037 | parseType: typed.parseType,
|
2038 | parseParamType: typed.parseParamType,
|
2039 | stringify: typed.stringify
|
2040 | };
|
2041 | }());
|
2042 |
|