UNPKG

102 kBJavaScriptView Raw
1'use strict';
2
3var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; })();
4
5/**
6 * # Typecheck Transformer
7 */
8
9Object.defineProperty(exports, "__esModule", {
10 value: true
11});
12
13exports.default = function (_ref) {
14 var t = _ref.types;
15 var template = _ref.template;
16
17 /**
18 * Binary Operators that can only produce boolean results.
19 */
20 var BOOLEAN_BINARY_OPERATORS = ['==', '===', '>=', '<=', '>', '<', 'instanceof'];
21
22 var checks = createChecks();
23 var staticChecks = createStaticChecks();
24
25 var checkIsArray = expression('Array.isArray(input)');
26 var checkIsMap = expression('input instanceof Map');
27 var checkIsSet = expression('input instanceof Set');
28 var checkIsGenerator = expression('typeof input === \'function\' && input.generator');
29 var checkIsIterable = expression('input && typeof input[Symbol.iterator] === \'function\'');
30 var checkIsObject = expression('input != null && typeof input === \'object\'');
31 var checkNotNull = expression('input != null');
32 var checkEquals = expression('input === expected');
33
34 var declareTypeChecker = template('\n const id = function id (input) {\n return check;\n };\n ');
35
36 var guard = template('\n if (!check) {\n throw new TypeError(message);\n }\n ');
37
38 var thrower = template('\n if (check) {\n ret;\n }\n else {\n throw new TypeError(message);\n }\n ');
39
40 var guardInline = expression('\n (id => {\n if (!check) {\n throw new TypeError(message);\n }\n return id;\n })(input)\n ');
41
42 var guardFn = expression('\n function name (id) {\n if (!check) {\n throw new TypeError(message);\n }\n return id;\n }\n ');
43
44 var readableName = expression('\n input === null ? \'null\' : typeof input === \'object\' && input.constructor ? input.constructor.name || \'[Unknown Object]\' : typeof input\n ');
45
46 var checkMapKeys = expression('\n input instanceof Map && Array.from(input.keys()).every(key => keyCheck)\n ');
47
48 var checkMapValues = expression('\n input instanceof Map && Array.from(input.values()).every(value => valueCheck)\n ');
49
50 var checkMapEntries = expression('\n input instanceof Map && Array.from(input).every(([key, value]) => keyCheck && valueCheck)\n ');
51
52 var checkSetEntries = expression('\n input instanceof Set && Array.from(input).every(value => valueCheck)\n ');
53
54 var PRAGMA_IGNORE_STATEMENT = /typecheck:\s*ignore\s+statement/i;
55 var PRAGMA_IGNORE_FILE = /typecheck:\s*ignore\s+file/i;
56
57 var visitors = {
58 Statement: function Statement(path) {
59 maybeSkip(path);
60 },
61 TypeAlias: function TypeAlias(path) {
62 if (maybeSkip(path)) {
63 return;
64 }
65 path.replaceWith(createTypeAliasChecks(path));
66 },
67 InterfaceDeclaration: function InterfaceDeclaration(path) {
68 if (maybeSkip(path)) {
69 return;
70 }
71 path.replaceWith(createInterfaceChecks(path));
72 },
73 ExportNamedDeclaration: function ExportNamedDeclaration(path) {
74 if (maybeSkip(path)) {
75 return;
76 }
77 var node = path.node;
78 var scope = path.scope;
79
80 if (node.declaration && node.declaration.type === 'TypeAlias') {
81 path.replaceWith(t.exportNamedDeclaration(createTypeAliasChecks(path.get('declaration')), [], null));
82 }
83 },
84 ImportDeclaration: function ImportDeclaration(path) {
85 if (maybeSkip(path)) {
86 return;
87 }
88 if (path.node.importKind !== 'type') {
89 return;
90 }
91
92 var _path$get$map$reduce = path.get('specifiers').map(function (specifier) {
93 var local = specifier.get('local');
94 var tmpId = path.scope.generateUidIdentifierBasedOnNode(local.node);
95 var replacement = t.importSpecifier(tmpId, specifier.node.imported);
96 var id = t.identifier(local.node.name);
97
98 id.isTypeChecker = true;
99 var declarator = t.variableDeclarator(id, tmpId);
100 declarator.isTypeChecker = true;
101 return [declarator, replacement];
102 }).reduce(function (_ref2, _ref3) {
103 var _ref5 = _slicedToArray(_ref2, 2);
104
105 var declarators = _ref5[0];
106 var specifiers = _ref5[1];
107
108 var _ref4 = _slicedToArray(_ref3, 2);
109
110 var declarator = _ref4[0];
111 var specifier = _ref4[1];
112
113 declarators.push(declarator);
114 specifiers.push(specifier);
115 return [declarators, specifiers];
116 }, [[], []]);
117
118 var _path$get$map$reduce2 = _slicedToArray(_path$get$map$reduce, 2);
119
120 var declarators = _path$get$map$reduce2[0];
121 var specifiers = _path$get$map$reduce2[1];
122
123 var declaration = t.variableDeclaration('var', declarators);
124 declaration.isTypeChecker = true;
125
126 path.replaceWithMultiple([t.importDeclaration(specifiers, path.node.source), declaration]);
127 },
128
129 Function: {
130 enter: function enter(path) {
131 var _node$body$body;
132
133 if (maybeSkip(path)) {
134 return;
135 }
136
137 var node = path.node;
138 var scope = path.scope;
139
140 var paramChecks = collectParamChecks(path);
141 if (node.type === "ArrowFunctionExpression" && node.expression) {
142 node.expression = false;
143 node.body = t.blockStatement([t.returnStatement(node.body)]);
144 }
145 if (node.returnType) {
146 // Create a function which can verify this return type
147 var annotation = node.returnType;
148 if (annotation.type === 'TypeAnnotation') {
149 annotation = annotation.typeAnnotation;
150 }
151 if (isGeneratorAnnotation(annotation)) {
152 annotation = annotation.typeParameters && annotation.typeParameters.params.length > 1 ? annotation.typeParameters.params[1] : t.anyTypeAnnotation();
153 }
154 var _name = scope.generateUidIdentifierBasedOnNode(path.node);
155 var _id = scope.generateUidIdentifier('id');
156 var check = checkAnnotation(_id, annotation, scope);
157 if (check) {
158 var returnGuard = guardFn({
159 id: _id,
160 name: _name,
161 check: check,
162 message: returnTypeErrorMessage(path, path.node, _id)
163 });
164 returnGuard.hasBeenTypeChecked = true;
165 node.returnGuardName = _name;
166 node.body.body.unshift(returnGuard);
167 }
168 }
169 (_node$body$body = node.body.body).unshift.apply(_node$body$body, _toConsumableArray(paramChecks));
170 node.savedTypeAnnotation = node.returnType;
171 node.returnCount = 0;
172 node.yieldCount = 0;
173 },
174 exit: function exit(path) {
175 var node = path.node;
176 var scope = path.scope;
177
178 var isVoid = node.savedTypeAnnotation ? maybeNullableAnnotation(node.savedTypeAnnotation) : null;
179 if (!node.returnCount && isVoid === false) {
180 var annotation = node.savedTypeAnnotation;
181 if (annotation.type === 'TypeAnnotation') {
182 annotation = annotation.typeAnnotation;
183 }
184 if (node.generator && isGeneratorAnnotation(annotation) && annotation.typeParameters && annotation.typeParameters.params.length > 1) {
185 annotation = annotation.typeParameters.params[1];
186 }
187 throw path.buildCodeFrameError('Function ' + (node.id ? '"' + node.id.name + '" ' : '') + 'did not return a value, expected ' + humanReadableType(annotation));
188 }
189 }
190 },
191
192 YieldExpression: function YieldExpression(path) {
193 var fn = path.getFunctionParent();
194 if (!fn) {
195 return;
196 }
197 fn.yieldCount++;
198 if (!isGeneratorAnnotation(fn.node.returnType) || maybeSkip(path)) {
199 return;
200 }
201 var node = path.node;
202 var parent = path.parent;
203 var scope = path.scope;
204
205 var annotation = fn.node.returnType;
206 if (annotation.type === 'NullableTypeAnnotation' || annotation.type === 'TypeAnnotation') {
207 annotation = annotation.typeAnnotation;
208 }
209 if (!annotation.typeParameters || annotation.typeParameters.params.length === 0) {
210 return;
211 }
212
213 var yieldType = annotation.typeParameters.params[0];
214 var nextType = annotation.typeParameters.params[2];
215 var ok = staticCheckAnnotation(path.get("argument"), yieldType);
216 if (ok === true && !nextType) {
217 return;
218 } else if (ok === false) {
219 throw path.buildCodeFrameError('Function ' + (fn.node.id ? '"' + fn.node.id.name + '" ' : '') + 'yielded an invalid type, expected ' + humanReadableType(yieldType) + ' got ' + humanReadableType(getAnnotation(path.get('argument'))));
220 }
221 var input = node.argument || t.identifier('undefined');
222 var id = scope.generateUidIdentifierBasedOnNode(input);
223 var check = checkAnnotation(id, yieldType, scope);
224 if (check) {
225 var yielder = t.yieldExpression(guardInline({
226 id: id,
227 input: input,
228 check: check,
229 message: yieldTypeErrorMessage(path, fn.node, id)
230 }));
231 yielder.hasBeenTypeChecked = true;
232 if (nextType) {
233 var _id2 = scope.generateUidIdentifierBasedOnNode(yielder);
234 var _check = checkAnnotation(_id2, nextType, scope);
235 if (_check) {
236 path.replaceWith(guardInline({
237 id: _id2,
238 input: yielder,
239 check: _check,
240 message: yieldNextTypeErrorMessage(path, fn.node, _id2)
241 }));
242 } else {
243 path.replaceWith(yielder);
244 }
245 } else {
246 path.replaceWith(yielder);
247 }
248 } else if (nextType) {
249 var yielder = t.yieldExpression(node.argument);
250 yielder.hasBeenTypeChecked = true;
251 var _id3 = scope.generateUidIdentifierBasedOnNode(yielder);
252 var _check2 = checkAnnotation(_id3, nextType, scope);
253 if (_check2) {
254 path.replaceWith(guardInline({
255 id: _id3,
256 input: yielder,
257 check: _check2,
258 message: yieldNextTypeErrorMessage(path, fn.node, _id3)
259 }));
260 }
261 }
262 },
263 ReturnStatement: function ReturnStatement(path) {
264 var fn = path.getFunctionParent();
265 if (!fn) {
266 return;
267 }
268 fn.node.returnCount++;
269 if (maybeSkip(path)) {
270 return;
271 }
272 var node = path.node;
273 var parent = path.parent;
274 var scope = path.scope;
275 var _fn$node = fn.node;
276 var returnType = _fn$node.returnType;
277 var returnGuardName = _fn$node.returnGuardName;
278
279 if (!returnType || !returnGuardName) {
280 return;
281 }
282 if (!node.argument) {
283 if (maybeNullableAnnotation(returnType) === false) {
284 throw path.buildCodeFrameError('Function ' + (fn.node.id ? '"' + fn.node.id.name + '" ' : '') + 'did not return a value, expected ' + humanReadableType(returnType));
285 }
286 return;
287 }
288 var annotation = returnType;
289 if (annotation.type === 'TypeAnnotation') {
290 annotation = annotation.typeAnnotation;
291 }
292 if (isGeneratorAnnotation(annotation)) {
293 annotation = annotation.typeParameters && annotation.typeParameters.params.length > 1 ? annotation.typeParameters.params[1] : t.anyTypeAnnotation();
294 }
295 var ok = staticCheckAnnotation(path.get("argument"), annotation);
296 if (ok === true) {
297 return;
298 } else if (ok === false) {
299 throw path.buildCodeFrameError('Function ' + (fn.node.id ? '"' + fn.node.id.name + '" ' : '') + 'returned an invalid type, expected ' + humanReadableType(annotation) + ' got ' + humanReadableType(getAnnotation(path.get('argument'))));
300 }
301 var returner = t.returnStatement(t.callExpression(fn.node.returnGuardName, [node.argument]));
302 returner.hasBeenTypeChecked = true;
303 path.replaceWith(returner);
304 },
305 VariableDeclaration: function VariableDeclaration(path) {
306 if (maybeSkip(path)) {
307 return;
308 }
309 var node = path.node;
310 var scope = path.scope;
311
312 var collected = [];
313 var declarations = path.get("declarations");
314 for (var i = 0; i < node.declarations.length; i++) {
315 var declaration = node.declarations[i];
316 var _id4 = declaration.id;
317 var init = declaration.init;
318
319 if (!_id4.typeAnnotation || _id4.hasBeenTypeChecked) {
320 continue;
321 }
322 _id4.savedTypeAnnotation = _id4.typeAnnotation;
323 _id4.hasBeenTypeChecked = true;
324 var ok = staticCheckAnnotation(declarations[i], _id4.typeAnnotation);
325 if (ok === true) {
326 continue;
327 } else if (ok === false) {
328 throw path.buildCodeFrameError('Invalid assignment value, expected ' + humanReadableType(_id4.typeAnnotation) + ' got ' + humanReadableType(getAnnotation(declarations[i])));
329 }
330 var check = checkAnnotation(_id4, _id4.typeAnnotation, scope);
331 if (check) {
332 collected.push(guard({
333 check: check,
334 message: varTypeErrorMessage(_id4, scope)
335 }));
336 }
337 }
338 if (collected.length > 0) {
339 var check = collected.reduce(function (check, branch) {
340 branch.alternate = check;
341 return branch;
342 });
343 if (path.parent.type === 'Program' || path.parent.type === 'BlockStatement') {
344 path.insertAfter(check);
345 } else if (path.parentPath.isForXStatement() || path.parentPath.isForStatement() || path.parentPath.isForInStatement()) {
346 var body = path.parentPath.get('body');
347 if (body.type !== 'BlockStatement') {
348 var block = t.blockStatement([body.node]);
349 body.replaceWith(block);
350 body = path.parentPath.get('body');
351 }
352 var children = body.get('body');
353 if (children.length === 0) {
354 body.replaceWith(check);
355 } else {
356 children[0].insertBefore(check);
357 }
358 } else if (path.parent.type === 'ExportNamedDeclaration' || path.parent.type === 'ExportDefaultDeclaration' || path.parent.type === 'ExportAllDeclaration') {
359 path.parentPath.insertAfter(check);
360 } else {
361 path.replaceWith(t.blockStatement([node, check]));
362 }
363 }
364 },
365 AssignmentExpression: function AssignmentExpression(path) {
366 if (maybeSkip(path)) {
367 return;
368 }
369 var node = path.node;
370 var scope = path.scope;
371
372 var left = path.get('left');
373 var annotation = undefined;
374 if (node.hasBeenTypeChecked || node.left.hasBeenTypeChecked) {
375 return;
376 } else if (left.isMemberExpression()) {
377 annotation = getAnnotation(left);
378 } else if (t.isIdentifier(node.left)) {
379 var binding = scope.getBinding(node.left.name);
380 if (!binding) {
381 return;
382 } else if (binding.path.type !== 'VariableDeclarator') {
383 return;
384 }
385 annotation = left.getTypeAnnotation();
386 if (annotation.type === 'AnyTypeAnnotation') {
387 var item = binding.path.get('id');
388 annotation = item.node.savedTypeAnnotation || item.getTypeAnnotation();
389 }
390 } else {
391 return;
392 }
393
394 node.hasBeenTypeChecked = true;
395 node.left.hasBeenTypeChecked = true;
396 var id = node.left;
397 var right = path.get('right');
398 if (annotation.type === 'AnyTypeAnnotation') {
399 annotation = getAnnotation(right);
400 if (allowsAny(annotation)) {
401 return;
402 }
403 }
404 var ok = staticCheckAnnotation(right, annotation);
405 if (ok === true) {
406 return;
407 } else if (ok === false) {
408 throw path.buildCodeFrameError('Invalid assignment value, expected ' + humanReadableType(annotation) + ' got ' + humanReadableType(getAnnotation(right)));
409 }
410 var check = checkAnnotation(id, annotation, scope);
411 if (!id.typeAnnotation) {
412 id.typeAnnotation = annotation;
413 }
414 id.hasBeenTypeChecked = true;
415 if (check) {
416 var parent = path.getStatementParent();
417 parent.insertAfter(guard({
418 check: check,
419 message: varTypeErrorMessage(id, scope)
420 }));
421 }
422 },
423 TypeCastExpression: function TypeCastExpression(path) {
424 var node = path.node;
425
426 var target = undefined;
427 switch (node.expression.type) {
428 case 'Identifier':
429 target = node.expression;
430 break;
431 case 'AssignmentExpression':
432 target = node.expression.left;
433 break;
434 default:
435 // unsupported.
436 return;
437 }
438 var id = path.scope.getBindingIdentifier(target.name);
439 if (!id) {
440 return;
441 }
442 id.savedTypeAnnotation = path.getTypeAnnotation();
443 },
444 ForOfStatement: function ForOfStatement(path) {
445 if (maybeSkip(path)) {
446 return;
447 }
448 var left = path.get('left');
449 var right = path.get('right');
450 var rightAnnotation = getAnnotation(right);
451 var leftAnnotation = left.isVariableDeclaration() ? getAnnotation(left.get('declarations')[0].get('id')) : getAnnotation(left);
452 if (rightAnnotation.type !== 'VoidTypeAnnotation') {
453 var ok = maybeIterableAnnotation(rightAnnotation);
454 if (ok === false) {
455 throw path.buildCodeFrameError('Cannot iterate ' + humanReadableType(rightAnnotation));
456 }
457 }
458 var id = undefined;
459 if (right.isIdentifier()) {
460 id = right.node;
461 } else {
462 id = path.scope.generateUidIdentifierBasedOnNode(right.node);
463 path.scope.push({ id: id });
464 var replacement = t.expressionStatement(t.assignmentExpression('=', id, right.node));
465 path.insertBefore(replacement);
466 right.replaceWith(id);
467 }
468 path.insertBefore(guard({
469 check: checks.iterable({ input: id }),
470 message: t.binaryExpression('+', t.stringLiteral('Expected ' + (0, _babelGenerator2.default)(right.node).code + ' to be iterable, got '), readableName({ input: id }))
471 }));
472
473 if (rightAnnotation.type !== 'GenericTypeAnnotation' || rightAnnotation.id.name !== 'Iterable' || !rightAnnotation.typeParameters || !rightAnnotation.typeParameters.params.length) {
474 return;
475 }
476
477 var annotation = rightAnnotation.typeParameters.params[0];
478 if (compareAnnotations(annotation, leftAnnotation) === false) {
479 throw path.buildCodeFrameError('Invalid iterator type, expected ' + humanReadableType(annotation) + ' got ' + humanReadableType(leftAnnotation));
480 }
481 }
482 };
483
484 return {
485 visitor: {
486 Program: function Program(path) {
487 var _iteratorNormalCompletion = true;
488 var _didIteratorError = false;
489 var _iteratorError = undefined;
490
491 try {
492 for (var _iterator = path.get('body')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
493 var child = _step.value;
494
495 if (maybeSkipFile(child)) {
496 return;
497 }
498 }
499 } catch (err) {
500 _didIteratorError = true;
501 _iteratorError = err;
502 } finally {
503 try {
504 if (!_iteratorNormalCompletion && _iterator.return) {
505 _iterator.return();
506 }
507 } finally {
508 if (_didIteratorError) {
509 throw _iteratorError;
510 }
511 }
512 }
513
514 path.traverse(visitors);
515 }
516 }
517 };
518
519 function isThisMemberExpression(path) {
520 var node = path.node;
521
522 if (node.type === 'ThisExpression') {
523 return true;
524 } else if (node.type === 'MemberExpression') {
525 return isThisMemberExpression(path.get('object'));
526 } else {
527 return false;
528 }
529 }
530
531 function isGeneratorAnnotation(annotation) {
532 if (!annotation) {
533 return false;
534 }
535 if (annotation.type === 'TypeAnnotation' || annotation.type === 'NullableTypeAnnotation') {
536 annotation = annotation.typeAnnotation;
537 }
538 return annotation.type === 'GenericTypeAnnotation' && annotation.id.name === 'Generator';
539 }
540
541 function createChecks() {
542 return {
543 number: expression('typeof input === \'number\''),
544 numericLiteral: checkNumericLiteral,
545 boolean: expression('typeof input === \'boolean\''),
546 booleanLiteral: checkBooleanLiteral,
547 function: expression('typeof input === \'function\''),
548 string: expression('typeof input === \'string\''),
549 stringLiteral: checkStringLiteral,
550 symbol: expression('typeof input === \'symbol\''),
551 undefined: expression('input === undefined'),
552 null: expression('input === null'),
553 void: expression('input == null'),
554 instanceof: expression('input instanceof type'),
555 type: expression('type(input)'),
556 mixed: function mixed() {
557 return null;
558 },
559 any: function any() {
560 return null;
561 },
562 union: checkUnion,
563 intersection: checkIntersection,
564 array: checkArray,
565 map: checkMap,
566 set: checkSet,
567 generator: checkGenerator,
568 iterable: checkIterable,
569 tuple: checkTuple,
570 object: checkObject,
571 nullable: checkNullable,
572 typeof: checkTypeof
573 };
574 }
575
576 function createStaticChecks() {
577 return {
578 symbol: function symbol(path) {
579 return maybeSymbolAnnotation(getAnnotation(path));
580 },
581 instanceof: function _instanceof(_ref6) {
582 var path = _ref6.path;
583 var annotation = _ref6.annotation;
584
585 var type = createTypeExpression(annotation.id);
586
587 var node = path.node;
588 var scope = path.scope;
589
590 if (type.name === 'Object' && node.type === 'ObjectExpression' && !scope.hasBinding('Object')) {
591 return true;
592 } else if (type.name === 'Map' && !scope.hasBinding('Map')) {
593 return null;
594 } else if (type.name === 'Set' && !scope.hasBinding('Set')) {
595 return null;
596 }
597 return maybeInstanceOfAnnotation(getAnnotation(path), type, annotation.typeParameters ? annotation.typeParameters.params : []);
598 },
599 type: (function (_type) {
600 function type(_x) {
601 return _type.apply(this, arguments);
602 }
603
604 type.toString = function () {
605 return _type.toString();
606 };
607
608 return type;
609 })(function (_ref7) {
610 var path = _ref7.path;
611 var type = _ref7.type;
612
613 return null;
614 })
615 };
616 }
617
618 function compareAnnotations(a, b) {
619 if (a.type === 'TypeAnnotation') {
620 a = a.typeAnnotation;
621 }
622 if (b.type === 'TypeAnnotation') {
623 b = b.typeAnnotation;
624 }
625 switch (a.type) {
626 case 'StringTypeAnnotation':
627 return maybeStringAnnotation(b);
628 case 'StringLiteralTypeAnnotation':
629 return compareStringLiteralAnnotations(a, b);
630 case 'NumberTypeAnnotation':
631 return maybeNumberAnnotation(b);
632 case 'NumericLiteralTypeAnnotation':
633 return compareNumericLiteralAnnotations(a, b);
634 case 'BooleanTypeAnnotation':
635 return maybeBooleanAnnotation(b);
636 case 'BooleanLiteralTypeAnnotation':
637 return compareBooleanLiteralAnnotations(a, b);
638 case 'FunctionTypeAnnotation':
639 return maybeFunctionAnnotation(b);
640 case 'AnyTypeAnnotation':
641 return null;
642 case 'MixedTypeAnnotation':
643 return null;
644 case 'ObjectTypeAnnotation':
645 return compareObjectAnnotation(a, b);
646 case 'ArrayTypeAnnotation':
647 return compareArrayAnnotation(a, b);
648 case 'GenericTypeAnnotation':
649 return compareGenericAnnotation(a, b);
650 case 'TupleTypeAnnotation':
651 return compareTupleAnnotation(a, b);
652 case 'UnionTypeAnnotation':
653 return compareUnionAnnotation(a, b);
654 case 'IntersectionTypeAnnotation':
655 return compareIntersectionAnnotation(a, b);
656 case 'NullableTypeAnnotation':
657 return compareNullableAnnotation(a, b);
658 default:
659 return null;
660 }
661 }
662
663 function compareStringLiteralAnnotations(a, b) {
664 if (b.type === 'StringLiteralTypeAnnotation') {
665 return a.value === b.value;
666 } else {
667 return maybeStringAnnotation(b) === false ? false : null;
668 }
669 }
670
671 function compareBooleanLiteralAnnotations(a, b) {
672 if (b.type === 'BooleanLiteralTypeAnnotation') {
673 return a.value === b.value;
674 } else {
675 return maybeBooleanAnnotation(b) === false ? false : null;
676 }
677 }
678
679 function compareNumericLiteralAnnotations(a, b) {
680 if (b.type === 'NumericLiteralTypeAnnotation') {
681 return a.value === b.value;
682 } else {
683 return maybeNumberAnnotation(b) === false ? false : null;
684 }
685 }
686
687 function unionComparer(a, b, comparator) {
688 if (!a.types || a.types.length === 0) {
689 return null;
690 }
691 var falseCount = 0;
692 var trueCount = 0;
693 if (!a.types) {
694 return null;
695 }
696 var _iteratorNormalCompletion2 = true;
697 var _didIteratorError2 = false;
698 var _iteratorError2 = undefined;
699
700 try {
701 for (var _iterator2 = a.types[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
702 var _type2 = _step2.value;
703
704 var result = comparator(_type2, b);
705 if (result === true) {
706 if (b.type !== 'UnionTypeAnnotation') {
707 return true;
708 }
709 trueCount++;
710 } else if (result === false) {
711 if (b.type === 'UnionTypeAnnotation') {
712 return false;
713 }
714 falseCount++;
715 }
716 }
717 } catch (err) {
718 _didIteratorError2 = true;
719 _iteratorError2 = err;
720 } finally {
721 try {
722 if (!_iteratorNormalCompletion2 && _iterator2.return) {
723 _iterator2.return();
724 }
725 } finally {
726 if (_didIteratorError2) {
727 throw _iteratorError2;
728 }
729 }
730 }
731
732 if (falseCount === a.types.length) {
733 return false;
734 } else if (trueCount === a.types.length) {
735 return true;
736 } else {
737 return null;
738 }
739 }
740
741 function intersectionComparer(a, b, comparator) {
742 var falseCount = 0;
743 var trueCount = 0;
744 if (!a.types) {
745 return null;
746 }
747 var _iteratorNormalCompletion3 = true;
748 var _didIteratorError3 = false;
749 var _iteratorError3 = undefined;
750
751 try {
752 for (var _iterator3 = a.types[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
753 var _type3 = _step3.value;
754
755 var result = comparator(_type3, b);
756 if (result === true) {
757 trueCount++;
758 } else if (result === false) {
759 return false;
760 }
761 }
762 } catch (err) {
763 _didIteratorError3 = true;
764 _iteratorError3 = err;
765 } finally {
766 try {
767 if (!_iteratorNormalCompletion3 && _iterator3.return) {
768 _iterator3.return();
769 }
770 } finally {
771 if (_didIteratorError3) {
772 throw _iteratorError3;
773 }
774 }
775 }
776
777 if (trueCount === a.types.length) {
778 return true;
779 } else {
780 return null;
781 }
782 }
783
784 function compareObjectAnnotation(a, b) {
785 switch (b.type) {
786 case 'ObjectTypeAnnotation':
787 break;
788 case 'TypeAnnotation':
789 case 'FunctionTypeParam':
790 case 'NullableTypeAnnotation':
791 return compareObjectAnnotation(a, b.typeAnnotation);
792 case 'UnionTypeAnnotation':
793 return unionComparer(a, b, compareObjectAnnotation);
794 case 'IntersectionTypeAnnotation':
795 return intersectionComparer(a, b, compareObjectAnnotation);
796 case 'VoidTypeAnnotation':
797 case 'BooleanTypeAnnotation':
798 case 'BooleanLiteralTypeAnnotation':
799 case 'StringTypeAnnotation':
800 case 'StringLiteralTypeAnnotation':
801 case 'NumberTypeAnnotation':
802 case 'NumericLiteralTypeAnnotation':
803 case 'FunctionTypeAnnotation':
804 return false;
805 default:
806 return null;
807 }
808
809 // We're comparing two object annotations.
810 var allTrue = true;
811 var _iteratorNormalCompletion4 = true;
812 var _didIteratorError4 = false;
813 var _iteratorError4 = undefined;
814
815 try {
816 for (var _iterator4 = a.properties[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
817 var aprop = _step4.value;
818
819 var found = false;
820 var _iteratorNormalCompletion5 = true;
821 var _didIteratorError5 = false;
822 var _iteratorError5 = undefined;
823
824 try {
825 for (var _iterator5 = b.properties[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
826 var bprop = _step5.value;
827
828 if (bprop.key.name === aprop.key.name) {
829 var result = compareAnnotations(aprop.value, bprop.value);
830 if (result === false && !(aprop.optional && (bprop.optional || maybeNullableAnnotation(bprop.value) === true))) {
831 return false;
832 } else {
833 found = result;
834 }
835 break;
836 }
837 }
838 } catch (err) {
839 _didIteratorError5 = true;
840 _iteratorError5 = err;
841 } finally {
842 try {
843 if (!_iteratorNormalCompletion5 && _iterator5.return) {
844 _iterator5.return();
845 }
846 } finally {
847 if (_didIteratorError5) {
848 throw _iteratorError5;
849 }
850 }
851 }
852
853 if (found === false && !aprop.optional) {
854 return false;
855 }
856 allTrue = allTrue && found === true;
857 }
858 } catch (err) {
859 _didIteratorError4 = true;
860 _iteratorError4 = err;
861 } finally {
862 try {
863 if (!_iteratorNormalCompletion4 && _iterator4.return) {
864 _iterator4.return();
865 }
866 } finally {
867 if (_didIteratorError4) {
868 throw _iteratorError4;
869 }
870 }
871 }
872
873 return allTrue ? true : null;
874 }
875
876 function compareArrayAnnotation(a, b) {
877 switch (b.type) {
878 case 'TypeAnnotation':
879 case 'FunctionTypeParam':
880 case 'NullableTypeAnnotation':
881 return compareArrayAnnotation(a, b.typeAnnotation);
882 case 'UnionTypeAnnotation':
883 return unionComparer(a, b, compareArrayAnnotation);
884 case 'IntersectionTypeAnnotation':
885 return intersectionComparer(a, b, compareArrayAnnotation);
886 case 'VoidTypeAnnotation':
887 case 'BooleanTypeAnnotation':
888 case 'BooleanLiteralTypeAnnotation':
889 case 'StringTypeAnnotation':
890 case 'StringLiteralTypeAnnotation':
891 case 'NumberTypeAnnotation':
892 case 'NumericLiteralTypeAnnotation':
893 case 'FunctionTypeAnnotation':
894 return false;
895 default:
896 return null;
897 }
898 }
899
900 function compareGenericAnnotation(a, b) {
901 switch (b.type) {
902 case 'TypeAnnotation':
903 case 'FunctionTypeParam':
904 case 'NullableTypeAnnotation':
905 return compareGenericAnnotation(a, b.typeAnnotation);
906 case 'GenericTypeAnnotation':
907 if (b.id.name === a.id.name) {
908 return true;
909 } else {
910 return null;
911 }
912 case 'UnionTypeAnnotation':
913 return unionComparer(a, b, compareGenericAnnotation);
914 case 'IntersectionTypeAnnotation':
915 return intersectionComparer(a, b, compareGenericAnnotation);
916 default:
917 return null;
918 }
919 }
920
921 function compareTupleAnnotation(a, b) {
922 if (b.type === 'TupleTypeAnnotation') {
923 if (b.types.length === 0) {
924 return null;
925 } else if (b.types.length < a.types.length) {
926 return false;
927 }
928 return a.types.every(function (type, index) {
929 return compareAnnotations(type, b.types[index]);
930 });
931 }
932 switch (b.type) {
933 case 'TypeAnnotation':
934 case 'FunctionTypeParam':
935 case 'NullableTypeAnnotation':
936 return compareTupleAnnotation(a, b.typeAnnotation);
937 case 'UnionTypeAnnotation':
938 return unionComparer(a, b, compareTupleAnnotation);
939 case 'IntersectionTypeAnnotation':
940 return intersectionComparer(a, b, compareTupleAnnotation);
941 case 'VoidTypeAnnotation':
942 case 'BooleanTypeAnnotation':
943 case 'BooleanLiteralTypeAnnotation':
944 case 'StringTypeAnnotation':
945 case 'StringLiteralTypeAnnotation':
946 case 'NumberTypeAnnotation':
947 case 'NumericLiteralTypeAnnotation':
948 case 'FunctionTypeAnnotation':
949 return false;
950 default:
951 return null;
952 }
953 }
954
955 function compareUnionAnnotation(a, b) {
956 switch (b.type) {
957 case 'NullableTypeAnnotation':
958 return compareUnionAnnotation(a, b.typeAnnotation);
959 case 'AnyTypeAnnotation':
960 case 'MixedTypeAnnotation':
961 return null;
962 default:
963 return unionComparer(a, b, compareAnnotations);
964 }
965 }
966
967 function compareNullableAnnotation(a, b) {
968 switch (b.type) {
969 case 'TypeAnnotation':
970 case 'FunctionTypeParam':
971 return compareNullableAnnotation(a, b.typeAnnotation);
972 case 'NullableTypeAnnotation':
973 case 'VoidTypeAnnotation':
974 return null;
975 }
976 if (compareAnnotations(a.typeAnnotation, b) === true) {
977 return true;
978 } else {
979 return null;
980 }
981 }
982
983 function arrayExpressionToTupleAnnotation(path) {
984 var elements = path.get('elements');
985 return t.tupleTypeAnnotation(elements.map(function (element) {
986 return getAnnotation(element);
987 }));
988 }
989
990 function checkNullable(_ref8) {
991 var input = _ref8.input;
992 var type = _ref8.type;
993 var scope = _ref8.scope;
994
995 var check = checkAnnotation(input, type, scope);
996 if (!check) {
997 return;
998 }
999 return t.logicalExpression("||", checks.void({ input: input }), check);
1000 }
1001
1002 function checkTypeof(_ref9) {
1003 var input = _ref9.input;
1004 var annotation = _ref9.annotation;
1005 var scope = _ref9.scope;
1006
1007 switch (annotation.type) {
1008 case 'GenericTypeAnnotation':
1009 var id = annotation.id;
1010
1011 var path = Object.assign({}, input, { type: id.type, node: id, scope: scope });
1012 return checkAnnotation(input, getAnnotation(path), scope);
1013 default:
1014 return checkAnnotation(input, annotation, scope);
1015 }
1016 }
1017
1018 function checkStringLiteral(_ref10) {
1019 var input = _ref10.input;
1020 var annotation = _ref10.annotation;
1021
1022 return checkEquals({ input: input, expected: t.stringLiteral(annotation.value) });
1023 }
1024
1025 function checkNumericLiteral(_ref11) {
1026 var input = _ref11.input;
1027 var annotation = _ref11.annotation;
1028
1029 return checkEquals({ input: input, expected: t.numericLiteral(annotation.value) });
1030 }
1031
1032 function checkBooleanLiteral(_ref12) {
1033 var input = _ref12.input;
1034 var annotation = _ref12.annotation;
1035
1036 return checkEquals({ input: input, expected: t.booleanLiteral(annotation.value) });
1037 }
1038
1039 function checkUnion(_ref13) {
1040 var input = _ref13.input;
1041 var types = _ref13.types;
1042 var scope = _ref13.scope;
1043
1044 var checks = types.map(function (type) {
1045 return checkAnnotation(input, type, scope);
1046 }).filter(identity);
1047 return checks.reduce(function (last, check, index) {
1048 if (last == null) {
1049 return check;
1050 }
1051 return t.logicalExpression("||", last, check);
1052 }, null);
1053 }
1054
1055 function checkIntersection(_ref14) {
1056 var input = _ref14.input;
1057 var types = _ref14.types;
1058 var scope = _ref14.scope;
1059
1060 var checks = types.map(function (type) {
1061 return checkAnnotation(input, type, scope);
1062 }).filter(identity);
1063 return checks.reduce(function (last, check, index) {
1064 if (last == null) {
1065 return check;
1066 }
1067 return t.logicalExpression("&&", last, check);
1068 }, null);
1069 }
1070
1071 function checkMap(_ref15) {
1072 var input = _ref15.input;
1073 var types = _ref15.types;
1074 var scope = _ref15.scope;
1075
1076 var _types = _slicedToArray(types, 2);
1077
1078 var keyType = _types[0];
1079 var valueType = _types[1];
1080
1081 var key = t.identifier('key');
1082 var value = t.identifier('value');
1083 var keyCheck = keyType ? checkAnnotation(key, keyType, scope) : null;
1084 var valueCheck = valueType ? checkAnnotation(value, valueType, scope) : null;
1085 if (!keyCheck) {
1086 if (!valueCheck) {
1087 return checkIsMap({ input: input });
1088 } else {
1089 return checkMapValues({ input: input, value: value, valueCheck: valueCheck });
1090 }
1091 } else {
1092 if (!valueCheck) {
1093 return checkMapKeys({ input: input, key: key, keyCheck: keyCheck });
1094 } else {
1095 return checkMapEntries({ input: input, key: key, value: value, keyCheck: keyCheck, valueCheck: valueCheck });
1096 }
1097 }
1098 }
1099
1100 function checkSet(_ref16) {
1101 var input = _ref16.input;
1102 var types = _ref16.types;
1103 var scope = _ref16.scope;
1104
1105 var _types2 = _slicedToArray(types, 1);
1106
1107 var valueType = _types2[0];
1108
1109 var value = t.identifier('value');
1110 var valueCheck = valueType ? checkAnnotation(value, valueType, scope) : null;
1111 if (!valueCheck) {
1112 return checkIsSet({ input: input });
1113 } else {
1114 return checkSetEntries({ input: input, value: value, valueCheck: valueCheck });
1115 }
1116 }
1117
1118 function checkGenerator(_ref17) {
1119 var input = _ref17.input;
1120 var types = _ref17.types;
1121 var scope = _ref17.scope;
1122
1123 return checkIsGenerator({ input: input });
1124 }
1125
1126 function checkIterable(_ref18) {
1127 var input = _ref18.input;
1128 var types = _ref18.types;
1129 var scope = _ref18.scope;
1130
1131 return checkIsIterable({ input: input });
1132 }
1133
1134 function checkArray(_ref19) {
1135 var input = _ref19.input;
1136 var types = _ref19.types;
1137 var scope = _ref19.scope;
1138
1139 if (!types || types.length === 0) {
1140 return checkIsArray({ input: input });
1141 } else if (types.length === 1) {
1142 var item = t.identifier('item');
1143 var _type4 = types[0];
1144 var check = checkAnnotation(item, _type4, scope);
1145 if (!check) {
1146 return checkIsArray({ input: input });
1147 }
1148 return t.logicalExpression('&&', checkIsArray({ input: input }), t.callExpression(t.memberExpression(input, t.identifier('every')), [t.functionExpression(null, [item], t.blockStatement([t.returnStatement(check)]))]));
1149 } else {
1150 // This is a tuple
1151 var _checks = types.map(function (type, index) {
1152 return checkAnnotation(t.memberExpression(input, t.numericLiteral(index), true), type, scope);
1153 }).filter(identity);
1154
1155 var checkLength = t.binaryExpression('>=', t.memberExpression(input, t.identifier('length')), t.numericLiteral(types.length));
1156
1157 return _checks.reduce(function (last, check, index) {
1158 return t.logicalExpression("&&", last, check);
1159 }, t.logicalExpression('&&', checkIsArray({ input: input }), checkLength));
1160 }
1161 }
1162
1163 function checkTuple(_ref20) {
1164 var input = _ref20.input;
1165 var types = _ref20.types;
1166 var scope = _ref20.scope;
1167
1168 if (types.length === 0) {
1169 return checkIsArray({ input: input });
1170 }
1171
1172 // This is a tuple
1173 var checks = types.map(function (type, index) {
1174 return checkAnnotation(t.memberExpression(input, t.numericLiteral(index), true), type, scope);
1175 }).filter(identity);
1176
1177 var checkLength = t.binaryExpression('>=', t.memberExpression(input, t.identifier('length')), t.numericLiteral(types.length));
1178
1179 return checks.reduce(function (last, check, index) {
1180 return t.logicalExpression("&&", last, check);
1181 }, t.logicalExpression('&&', checkIsArray({ input: input }), checkLength));
1182 }
1183
1184 function checkObject(_ref21) {
1185 var input = _ref21.input;
1186 var properties = _ref21.properties;
1187 var scope = _ref21.scope;
1188
1189 if (input.type === 'ObjectPattern') {
1190 return checkObjectPattern({ input: input, properties: properties, scope: scope });
1191 }
1192 var check = properties.reduce(function (expr, prop, index) {
1193 var target = undefined;
1194
1195 target = t.memberExpression(input, prop.key);
1196 var check = checkAnnotation(target, prop.value, scope);
1197 if (check) {
1198 if (prop.optional) {
1199 check = t.logicalExpression('||', checks.undefined({ input: target }), check);
1200 }
1201 return t.logicalExpression("&&", expr, check);
1202 } else {
1203 return expr;
1204 }
1205 }, checkIsObject({ input: input }));
1206
1207 return check;
1208 }
1209
1210 function checkObjectPattern(_ref22) {
1211 var input = _ref22.input;
1212 var properties = _ref22.properties;
1213 var scope = _ref22.scope;
1214
1215 var propNames = properties.reduce(function (names, prop) {
1216 names[prop.key.name] = prop;
1217 return names;
1218 }, {});
1219 var propChecks = {};
1220 var _iteratorNormalCompletion6 = true;
1221 var _didIteratorError6 = false;
1222 var _iteratorError6 = undefined;
1223
1224 try {
1225 for (var _iterator6 = input.properties[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
1226 var item = _step6.value;
1227 var key = item.key;
1228 var _id5 = item.value;
1229
1230 var prop = propNames[key.name];
1231 if (!prop) {
1232 continue;
1233 }
1234 var check = checkAnnotation(_id5, prop.value, scope);
1235 if (check) {
1236 propChecks[key.name] = check;
1237 }
1238 }
1239 } catch (err) {
1240 _didIteratorError6 = true;
1241 _iteratorError6 = err;
1242 } finally {
1243 try {
1244 if (!_iteratorNormalCompletion6 && _iterator6.return) {
1245 _iterator6.return();
1246 }
1247 } finally {
1248 if (_didIteratorError6) {
1249 throw _iteratorError6;
1250 }
1251 }
1252 }
1253
1254 return Object.keys(propChecks).reduce(function (last, name) {
1255 var check = propChecks[name];
1256 if (last === null) {
1257 return check;
1258 } else {
1259 return t.logicalExpression('&&', last, check);
1260 }
1261 }, null);
1262 }
1263
1264 function createTypeAliasChecks(path) {
1265 var node = path.node;
1266 var scope = path.scope;
1267 var id = node.id;
1268 var annotation = node.right;
1269
1270 var input = t.identifier('input');
1271 var check = checkAnnotation(input, annotation, scope) || t.booleanLiteral(true);
1272 var declaration = declareTypeChecker({ id: id, check: check });
1273 declaration.isTypeChecker = true;
1274 declaration.savedTypeAnnotation = annotation;
1275 declaration.declarations[0].savedTypeAnnotation = annotation;
1276 return declaration;
1277 }
1278
1279 function createInterfaceChecks(path) {
1280 var node = path.node;
1281 var scope = path.scope;
1282 var id = node.id;
1283 var annotation = node.body;
1284
1285 var input = t.identifier('input');
1286 var check = node.extends.reduce(function (check, extender) {
1287 return t.logicalExpression('&&', check, checkAnnotation(input, t.genericTypeAnnotation(extender.id), path.scope));
1288 return check;
1289 }, checkAnnotation(input, annotation, scope) || t.booleanLiteral(true));
1290
1291 var declaration = declareTypeChecker({ id: id, check: check });
1292 declaration.isTypeChecker = true;
1293 return declaration;
1294 }
1295
1296 function checkAnnotation(input, annotation, scope) {
1297 switch (annotation.type) {
1298 case 'TypeAnnotation':
1299 case 'FunctionTypeParam':
1300 return checkAnnotation(input, annotation.typeAnnotation, scope);
1301 case 'TypeofTypeAnnotation':
1302 return checks.typeof({ input: input, annotation: annotation.argument, scope: scope });
1303 case 'GenericTypeAnnotation':
1304 if (annotation.id.name === 'Array') {
1305 return checks.array({ input: input, types: annotation.typeParameters ? annotation.typeParameters.params : [], scope: scope });
1306 } else if (annotation.id.name === 'Generator' && !scope.hasBinding('Generator')) {
1307 return checks.generator({ input: input, types: annotation.typeParameters ? annotation.typeParameters.params : [], scope: scope });
1308 } else if (annotation.id.name === 'Iterable' && !scope.hasBinding('Iterable')) {
1309 return checks.iterable({ input: input, types: annotation.typeParameters ? annotation.typeParameters.params : [], scope: scope });
1310 } else if (annotation.id.name === 'Map' && !scope.hasBinding('Map')) {
1311 return checks.map({ input: input, types: annotation.typeParameters ? annotation.typeParameters.params : [], scope: scope });
1312 } else if (annotation.id.name === 'Set' && !scope.hasBinding('Set')) {
1313 return checks.set({ input: input, types: annotation.typeParameters ? annotation.typeParameters.params : [], scope: scope });
1314 } else if (annotation.id.name === 'Function') {
1315 return checks.function({ input: input });
1316 } else if (annotation.id.name === 'Symbol') {
1317 return checks.symbol({ input: input });
1318 } else if (isTypeChecker(annotation.id, scope)) {
1319 return checks.type({ input: input, type: annotation.id });
1320 } else if (isPolymorphicType(annotation.id, scope)) {
1321 return;
1322 } else {
1323 return checks.instanceof({ input: input, type: createTypeExpression(annotation.id) });
1324 }
1325 case 'TupleTypeAnnotation':
1326 return checks.tuple({ input: input, types: annotation.types, scope: scope });
1327 case 'NumberTypeAnnotation':
1328 return checks.number({ input: input });
1329 case 'NumericLiteralTypeAnnotation':
1330 return checks.numericLiteral({ input: input, annotation: annotation });
1331 case 'BooleanTypeAnnotation':
1332 return checks.boolean({ input: input });
1333 case 'BooleanLiteralTypeAnnotation':
1334 return checks.booleanLiteral({ input: input, annotation: annotation });
1335 case 'StringTypeAnnotation':
1336 return checks.string({ input: input });
1337 case 'StringLiteralTypeAnnotation':
1338 return checks.stringLiteral({ input: input, annotation: annotation });
1339 case 'UnionTypeAnnotation':
1340 return checks.union({ input: input, types: annotation.types, scope: scope });
1341 case 'IntersectionTypeAnnotation':
1342 return checks.intersection({ input: input, types: annotation.types, scope: scope });
1343 case 'ObjectTypeAnnotation':
1344 return checks.object({ input: input, properties: annotation.properties || [], indexers: annotation.indexers, scope: scope });
1345 case 'ArrayTypeAnnotation':
1346 return checks.array({ input: input, types: [annotation.elementType || t.anyTypeAnnotation()], scope: scope });
1347 case 'FunctionTypeAnnotation':
1348 return checks.function({ input: input, params: annotation.params, returnType: annotation.returnType });
1349 case 'MixedTypeAnnotation':
1350 return checks.mixed({ input: input });
1351 case 'AnyTypeAnnotation':
1352 case 'ExistentialTypeParam':
1353 return checks.any({ input: input });
1354 case 'NullableTypeAnnotation':
1355 return checks.nullable({ input: input, type: annotation.typeAnnotation, scope: scope });
1356 case 'VoidTypeAnnotation':
1357 return checks.void({ input: input });
1358 }
1359 }
1360
1361 function staticCheckAnnotation(path, annotation) {
1362 var other = getAnnotation(path);
1363 switch (annotation.type) {
1364 case 'TypeAnnotation':
1365 case 'FunctionTypeParam':
1366 return staticCheckAnnotation(path, annotation.typeAnnotation);
1367 case 'GenericTypeAnnotation':
1368 if (isTypeChecker(annotation.id, path.scope)) {
1369 return staticChecks.type({ path: path, type: annotation.id });
1370 } else if (isPolymorphicType(annotation.id, path.scope)) {
1371 return;
1372 } else if (annotation.id.name === 'Symbol') {
1373 return staticChecks.symbol(path);
1374 } else {
1375 return staticChecks.instanceof({ path: path, annotation: annotation });
1376 }
1377 }
1378 return compareAnnotations(annotation, other);
1379 }
1380
1381 /**
1382 * Get the type annotation for a given node.
1383 */
1384 function getAnnotation(path) {
1385 var annotation = undefined;
1386 try {
1387 annotation = getAnnotationShallow(path);
1388 } catch (e) {
1389 if (e instanceof SyntaxError) {
1390 throw e;
1391 }
1392 console.error(e.stack);
1393 }
1394 while (annotation && annotation.type === 'TypeAnnotation') {
1395 annotation = annotation.typeAnnotation;
1396 }
1397 return annotation || t.anyTypeAnnotation();
1398 }
1399
1400 function getAnnotationShallow(path) {
1401 if (!path || !path.node) {
1402 return t.voidTypeAnnotation();
1403 }
1404 var node = path.node;
1405 var scope = path.scope;
1406
1407 if (node.type === 'TypeAlias') {
1408 return node.right;
1409 } else if (node.type === 'ClassProperty' && node.typeAnnotation) {
1410 return getClassPropertyAnnotation(path);
1411 } else if (node.type === 'ClassMethod' && node.returnType) {
1412 return getClassMethodAnnotation(path);
1413 } else if (node.type === 'ObjectProperty' && node.typeAnnotation) {
1414 return getObjectPropertyAnnotation(path);
1415 } else if (node.type === 'ObjectMethod' && node.returnType) {
1416 return getObjectMethodAnnotation(path);
1417 } else if (!node.typeAnnotation && !node.savedTypeAnnotation && !node.returnType) {
1418 switch (path.type) {
1419 case 'Identifier':
1420 var binding = scope.getBinding(node.name);
1421 if (!binding || !binding.identifier) {
1422 return path.getTypeAnnotation();
1423 }
1424 var id = binding.identifier;
1425 if (binding.path.type === 'ObjectPattern') {
1426 return getObjectPatternAnnotation(binding.path, node.name);
1427 }
1428 if (id.savedTypeAnnotation) {
1429 return id.savedTypeAnnotation;
1430 } else if (id.returnType) {
1431 return id.returnType;
1432 } else if (id.typeAnnotation) {
1433 return id.typeAnnotation;
1434 } else if (isPolymorphicType(id, scope)) {
1435 return t.anyTypeAnnotation();
1436 }
1437 return binding.constant ? binding.path.getTypeAnnotation() : path.getTypeAnnotation();
1438 case 'StringLiteral':
1439 case 'NumericLiteral':
1440 case 'BooleanLiteral':
1441 return createLiteralTypeAnnotation(path);
1442 case 'CallExpression':
1443 var callee = path.get('callee');
1444 if (callee.type === 'Identifier') {
1445 if (callee.name === 'Symbol') {
1446 return t.genericTypeAnnotation('Symbol');
1447 }
1448 var fn = getFunctionForIdentifier(callee);
1449 if (fn) {
1450 return getAnnotation(fn);
1451 }
1452 }
1453 break;
1454 case 'ThisExpression':
1455 return getThisExpressionAnnotation(path);
1456 case 'AssignmentExpression':
1457 return getAssignmentExpressionAnnotation(path);
1458 case 'MemberExpression':
1459 return getMemberExpressionAnnotation(path);
1460 case 'ArrayExpression':
1461 return getArrayExpressionAnnotation(path);
1462 case 'ObjectExpression':
1463 return getObjectExpressionAnnotation(path);
1464 case 'BinaryExpression':
1465 return getBinaryExpressionAnnotation(path);
1466 case 'BinaryExpression':
1467 return getBinaryExpressionAnnotation(path);
1468 case 'LogicalExpression':
1469 return getLogicalExpressionAnnotation(path);
1470 case 'ConditionalExpression':
1471 return getConditionalExpressionAnnotation(path);
1472 case 'ObjectMethod':
1473 return getObjectMethodAnnotation(path);
1474 case 'ObjectProperty':
1475 return getObjectPropertyAnnotation(path);
1476 case 'ClassDeclaration':
1477 return getClassDeclarationAnnotation(path);
1478 case 'ClassMethod':
1479 return getClassMethodAnnotation(path);
1480 case 'ClassProperty':
1481 return getClassPropertyAnnotation(path);
1482 default:
1483 return path.getTypeAnnotation();
1484
1485 }
1486 }
1487 return node.savedTypeAnnotation || node.returnType || node.typeAnnotation || path.getTypeAnnotation();
1488 }
1489
1490 function createLiteralTypeAnnotation(path) {
1491 var annotation = undefined;
1492 if (path.isStringLiteral()) {
1493 annotation = t.stringLiteralTypeAnnotation();
1494 } else if (path.isNumericLiteral()) {
1495 annotation = t.numericLiteralTypeAnnotation();
1496 } else if (path.isBooleanLiteral()) {
1497 annotation = t.booleanLiteralTypeAnnotation();
1498 } else {
1499 return path.getTypeAnnotation();
1500 }
1501 annotation.value = path.node.value;
1502 return annotation;
1503 }
1504
1505 function getObjectPatternAnnotation(path, name) {
1506 var annotation = keyByName(getAnnotation(path), name);
1507 var found = undefined;
1508 if (!path.node.properties) {
1509 return;
1510 }
1511 var _iteratorNormalCompletion7 = true;
1512 var _didIteratorError7 = false;
1513 var _iteratorError7 = undefined;
1514
1515 try {
1516 for (var _iterator7 = path.get('properties')[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
1517 var prop = _step7.value;
1518
1519 if (prop.node.value && prop.node.value.name === name) {
1520 found = prop.get('key');
1521 break;
1522 } else if (prop.node.key.type === 'Identifier' && prop.node.key.name === name) {
1523 found = prop.get('key');
1524 break;
1525 }
1526 }
1527 } catch (err) {
1528 _didIteratorError7 = true;
1529 _iteratorError7 = err;
1530 } finally {
1531 try {
1532 if (!_iteratorNormalCompletion7 && _iterator7.return) {
1533 _iterator7.return();
1534 }
1535 } finally {
1536 if (_didIteratorError7) {
1537 throw _iteratorError7;
1538 }
1539 }
1540 }
1541
1542 if (!annotation || !found) {
1543 return;
1544 }
1545 if (found.type === 'Identifier') {
1546 annotation.value.authoritative = false;
1547 return annotation.value;
1548 }
1549 }
1550
1551 function keyByName(node, name) {
1552 if (!node.properties) {
1553 return;
1554 }
1555 var _iteratorNormalCompletion8 = true;
1556 var _didIteratorError8 = false;
1557 var _iteratorError8 = undefined;
1558
1559 try {
1560 for (var _iterator8 = node.properties[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
1561 var prop = _step8.value;
1562
1563 if (prop.key && prop.key.name === name) {
1564 return prop;
1565 }
1566 }
1567 } catch (err) {
1568 _didIteratorError8 = true;
1569 _iteratorError8 = err;
1570 } finally {
1571 try {
1572 if (!_iteratorNormalCompletion8 && _iterator8.return) {
1573 _iterator8.return();
1574 }
1575 } finally {
1576 if (_didIteratorError8) {
1577 throw _iteratorError8;
1578 }
1579 }
1580 }
1581 }
1582
1583 function valueByName(node, name) {
1584 if (!node.properties) {
1585 return;
1586 }
1587 var _iteratorNormalCompletion9 = true;
1588 var _didIteratorError9 = false;
1589 var _iteratorError9 = undefined;
1590
1591 try {
1592 for (var _iterator9 = node.properties[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
1593 var prop = _step9.value;
1594
1595 if (prop.value && prop.value.name === name) {
1596 return prop;
1597 }
1598 }
1599 } catch (err) {
1600 _didIteratorError9 = true;
1601 _iteratorError9 = err;
1602 } finally {
1603 try {
1604 if (!_iteratorNormalCompletion9 && _iterator9.return) {
1605 _iterator9.return();
1606 }
1607 } finally {
1608 if (_didIteratorError9) {
1609 throw _iteratorError9;
1610 }
1611 }
1612 }
1613 }
1614
1615 function getObjectPropertyAnnotation(path) {
1616 var node = path.node;
1617
1618 var annotation = node.typeAnnotation || node.savedTypeAnnotation;
1619 if (!annotation) {
1620 if (node.value) {
1621 var value = path.get('value');
1622 if (value.isLiteral()) {
1623 annotation = createLiteralTypeAnnotation(value);
1624 } else {
1625 annotation = value.node.typeAnnotation || value.node.savedTypeAnnotation || t.anyTypeAnnotation();
1626 }
1627 } else {
1628 annotation = t.anyTypeAnnotation();
1629 }
1630 }
1631 return t.objectTypeProperty(node.key, annotation || t.anyTypeAnnotation());
1632 }
1633
1634 function getObjectMethodAnnotation(path) {
1635 var node = path.node;
1636
1637 return t.objectTypeProperty(t.identifier(node.key.name), t.functionTypeAnnotation(null, node.params.map(function (param) {
1638 return param.savedTypeAnnotation || param.typeAnnotation;
1639 }), null, node.savedTypeAnnotation || node.returnType || node.typeAnnotation || t.anyTypeAnnotation()));
1640 }
1641
1642 function getThisExpressionAnnotation(path) {
1643 var parent = path.parentPath;
1644 loop: while (parent) {
1645 switch (parent.type) {
1646 case 'ClassDeclaration':
1647 return getAnnotation(parent);
1648 case 'ClassBody':
1649 return getAnnotation(parent.parentPath);
1650 case 'ClassMethod':
1651 case 'ClassProperty':
1652 return getAnnotation(parent.parentPath.parentPath);
1653 case 'ObjectProperty':
1654 return getAnnotation(parent.parentPath);
1655 case 'ObjectMethod':
1656 return getAnnotation(parent.parentPath);
1657 case 'FunctionExpression':
1658 if (parent.parentPath.type === 'ObjectProperty') {
1659 return getAnnotation(parent.parentPath.parentPath);
1660 }
1661 break loop;
1662 case 'ArrowFunctionExpression':
1663 parent = parent.parentPath;
1664 continue;
1665 }
1666 if (parent.isFunction()) {
1667 break;
1668 }
1669 parent = parent.parentPath;
1670 }
1671 return t.objectTypeAnnotation([]);
1672 }
1673
1674 function getClassDeclarationAnnotation(path) {
1675 var body = path.get('body').get('body').map(getAnnotation).filter(function (annotation) {
1676 return annotation && annotation.type !== 'AnyTypeAnnotation';
1677 });
1678 return t.objectTypeAnnotation(body);
1679 }
1680
1681 function getAssignmentExpressionAnnotation(path) {
1682 if (path.node.operator === '=') {
1683 return getAnnotation(path.get('right'));
1684 }
1685 }
1686
1687 function getClassPropertyAnnotation(path) {
1688 var node = path.node;
1689
1690 if (node.computed) {
1691 return;
1692 }
1693 var annotation = node.typeAnnotation || (node.value ? node.value.savedTypeAnnotation || node.value.typeAnnotation : t.anyTypeAnnotation());
1694 return t.objectTypeProperty(node.key, annotation || t.anyTypeAnnotation());
1695 }
1696
1697 function getClassMethodAnnotation(path) {
1698 var node = path.node;
1699
1700 if (node.computed) {
1701 return;
1702 }
1703 if (node.kind === 'get') {
1704 return t.objectTypeProperty(node.key, node.savedTypeAnnotation || node.returnType || node.typeAnnotation || t.anyTypeAnnotation());
1705 } else if (node.kind === 'set') {
1706 return t.objectTypeProperty(node.key, node.params.map(function (param) {
1707 return param.savedTypeAnnotation || param.typeAnnotation;
1708 }).shift() || t.anyTypeAnnotation());
1709 } else {
1710 return t.objectTypeProperty(node.key, t.functionTypeAnnotation(null, node.params.map(function (param) {
1711 return param.savedTypeAnnotation || param.typeAnnotation || t.anyTypeAnnotation();
1712 }), null, node.savedTypeAnnotation || node.returnType || node.typeAnnotation || t.anyTypeAnnotation()));
1713 }
1714 }
1715
1716 function getBinaryExpressionAnnotation(path) {
1717 var node = path.node;
1718
1719 if (isBooleanExpression(node)) {
1720 return t.booleanTypeAnnotation();
1721 } else {
1722 return t.anyTypeAnnotation();
1723 }
1724 }
1725
1726 function getLogicalExpressionAnnotation(path) {
1727 var node = path.node;
1728
1729 if (isBooleanExpression(node)) {
1730 return t.booleanTypeAnnotation();
1731 } else {
1732 var left = path.get('left');
1733 var right = path.get('right');
1734 switch (node.operator) {
1735 case '&&':
1736 case '||':
1737 var _ref23 = [getAnnotation(left), getAnnotation(right)];
1738 left = _ref23[0];
1739 right = _ref23[1];
1740
1741 if (t.isUnionTypeAnnotation(left)) {
1742 if (t.isUnionTypeAnnotation(right)) {
1743 return t.unionTypeAnnotation(left.types.concat(right.types));
1744 } else {
1745 return t.unionTypeAnnotation(left.types.concat(right));
1746 }
1747 } else {
1748 return t.unionTypeAnnotation([left, right]);
1749 }
1750 }
1751 return t.anyTypeAnnotation();
1752 }
1753 }
1754
1755 function getConditionalExpressionAnnotation(path) {
1756 var node = path.node;
1757
1758 var consequent = getAnnotation(path.get('consequent'));
1759 var alternate = getAnnotation(path.get('alternate'));
1760 if (t.isUnionTypeAnnotation(consequent)) {
1761 if (t.isUnionTypeAnnotation(alternate)) {
1762 return t.unionTypeAnnotation(consequent.types.concat(alternate.types));
1763 } else {
1764 return t.unionTypeAnnotation(consequent.types.concat(alternate));
1765 }
1766 } else {
1767 return t.unionTypeAnnotation([consequent, alternate]);
1768 }
1769 }
1770
1771 function getArrayExpressionAnnotation(path) {
1772 return t.genericTypeAnnotation(t.identifier('Array'), t.typeParameterDeclaration(path.get('elements').map(getAnnotation)));
1773 }
1774
1775 function getObjectExpressionAnnotation(path) {
1776 var annotation = t.objectTypeAnnotation(path.get('properties').map(function (property) {
1777 if (property.computed) {
1778 return;
1779 } else {
1780 return getAnnotation(property);
1781 }
1782 }).filter(identity));
1783 return annotation;
1784 }
1785
1786 function getMemberExpressionAnnotation(path) {
1787 if (path.node.computed) {
1788 return getComputedMemberExpressionAnnotation(path);
1789 }
1790 var stack = [];
1791 var target = path;
1792 while (target.isMemberExpression()) {
1793 stack.push(target);
1794 if (target.node.computed) {
1795 break;
1796 }
1797 target = target.get('object');
1798 }
1799 var objectAnnotation = stack.reduceRight(function (last, target) {
1800 var annotation = last;
1801 if (annotation == null) {
1802 if (stack.length === 1) {
1803 annotation = getAnnotation(target.get('object'));
1804 } else {
1805 return getAnnotation(target);
1806 }
1807 }
1808
1809 switch (annotation.type) {
1810 case 'AnyTypeAnnotation':
1811 return annotation;
1812 case 'NullableTypeAnnotation':
1813 case 'TypeAnnotation':
1814 annotation = annotation.typeAnnotation;
1815 }
1816
1817 if (annotation.type === 'GenericTypeAnnotation') {
1818 var typeChecker = getTypeChecker(annotation.id, path.scope);
1819 if (typeChecker) {
1820 annotation = getAnnotation(typeChecker);
1821 } else {
1822 var binding = path.scope.getBinding(annotation.id.name);
1823 if (binding) {
1824 annotation = getAnnotation(binding.path);
1825 }
1826 }
1827 }
1828 switch (annotation.type) {
1829 case 'AnyTypeAnnotation':
1830 return annotation;
1831 case 'ObjectTypeAnnotation':
1832 var id = target.get('property').node;
1833 var _iteratorNormalCompletion10 = true;
1834 var _didIteratorError10 = false;
1835 var _iteratorError10 = undefined;
1836
1837 try {
1838 for (var _iterator10 = (annotation.properties || [])[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
1839 var _step10$value = _step10.value;
1840 var key = _step10$value.key;
1841 var value = _step10$value.value;
1842
1843 if (key.name === id.name) {
1844 return value;
1845 }
1846 }
1847 } catch (err) {
1848 _didIteratorError10 = true;
1849 _iteratorError10 = err;
1850 } finally {
1851 try {
1852 if (!_iteratorNormalCompletion10 && _iterator10.return) {
1853 _iterator10.return();
1854 }
1855 } finally {
1856 if (_didIteratorError10) {
1857 throw _iteratorError10;
1858 }
1859 }
1860 }
1861
1862 }
1863 return t.anyTypeAnnotation();
1864 }, null);
1865
1866 return objectAnnotation || path.getTypeAnnotation();
1867 }
1868
1869 function getComputedMemberExpressionAnnotation(path) {
1870 var object = path.get('object');
1871 var property = path.get('property');
1872 var objectAnnotation = getAnnotation(object);
1873 if (objectAnnotation.type === 'TypeAnnotation' || objectAnnotation.type === 'NullableTypeAnnotation') {
1874 objectAnnotation = objectAnnotation.typeAnnotation;
1875 }
1876 var propertyAnnotation = getAnnotation(property);
1877 if (propertyAnnotation.type === 'TypeAnnotation' || propertyAnnotation.type === 'NullableTypeAnnotation') {
1878 propertyAnnotation = propertyAnnotation.typeAnnotation;
1879 }
1880
1881 var _property$evaluate = property.evaluate();
1882
1883 var confident = _property$evaluate.confident;
1884 var value = _property$evaluate.value;
1885
1886 if (!confident) {
1887 return path.getTypeAnnotation();
1888 }
1889 switch (objectAnnotation.type) {
1890 case 'TupleTypeAnnotation':
1891 if (objectAnnotation.types.length === 0) {
1892 break;
1893 } else if (typeof value === 'number') {
1894 if (!objectAnnotation.types[value]) {
1895 throw path.buildCodeFrameError('Invalid computed member expression for tuple: ' + humanReadableType(objectAnnotation));
1896 }
1897 return objectAnnotation.types[value];
1898 } else {
1899 throw path.buildCodeFrameError('Invalid computed member expression for tuple: ' + humanReadableType(objectAnnotation));
1900 }
1901 break;
1902 }
1903 return path.getTypeAnnotation();
1904 }
1905
1906 function getFunctionForIdentifier(path) {
1907 if (path.type !== 'Identifier') {
1908 return false;
1909 }
1910 var ref = path.scope.getBinding(path.node.name);
1911 if (!ref) {
1912 return false;
1913 }
1914 return t.isFunction(ref.path.parent) && ref.path.parentPath;
1915 }
1916
1917 /**
1918 * Returns `true` if the annotation is definitely for an array,
1919 * otherwise `false`.
1920 */
1921 function isStrictlyArrayAnnotation(annotation) {
1922 switch (annotation.type) {
1923 case 'TypeAnnotation':
1924 case 'FunctionTypeParam':
1925 return isStrictlyArrayAnnotation(annotation.typeAnnotation);
1926 case 'GenericTypeAnnotation':
1927 return annotation.id.name === 'Array';
1928 case 'UnionTypeAnnotation':
1929 return annotation.types.every(isStrictlyArrayAnnotation);
1930 default:
1931 return false;
1932 }
1933 }
1934
1935 function compareMaybeUnion(annotation, comparator) {
1936 var falseCount = 0;
1937 var _iteratorNormalCompletion11 = true;
1938 var _didIteratorError11 = false;
1939 var _iteratorError11 = undefined;
1940
1941 try {
1942 for (var _iterator11 = annotation.types[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
1943 var _type5 = _step11.value;
1944
1945 var result = comparator(_type5);
1946 if (result === true) {
1947 return true;
1948 } else if (result === false) {
1949 falseCount++;
1950 }
1951 }
1952 } catch (err) {
1953 _didIteratorError11 = true;
1954 _iteratorError11 = err;
1955 } finally {
1956 try {
1957 if (!_iteratorNormalCompletion11 && _iterator11.return) {
1958 _iterator11.return();
1959 }
1960 } finally {
1961 if (_didIteratorError11) {
1962 throw _iteratorError11;
1963 }
1964 }
1965 }
1966
1967 if (falseCount === annotation.types.length) {
1968 return false;
1969 } else {
1970 return null;
1971 }
1972 }
1973
1974 /**
1975 * Returns `true` if the annotation is compatible with a number,
1976 * `false` if it definitely isn't, or `null` if we're not sure.
1977 */
1978 function maybeNumberAnnotation(annotation) {
1979 switch (annotation.type) {
1980 case 'TypeAnnotation':
1981 case 'FunctionTypeParam':
1982 case 'NullableTypeAnnotation':
1983 return maybeNumberAnnotation(annotation.typeAnnotation);
1984 case 'NumberTypeAnnotation':
1985 case 'NumericLiteralTypeAnnotation':
1986 return true;
1987 case 'GenericTypeAnnotation':
1988 switch (annotation.id.name) {
1989 case 'Array':
1990 case 'Function':
1991 case 'Object':
1992 case 'String':
1993 case 'Boolean':
1994 case 'Date':
1995 case 'RegExp':
1996 return false;
1997 default:
1998 return null;
1999 }
2000 case 'UnionTypeAnnotation':
2001 return compareMaybeUnion(annotation, maybeNumberAnnotation);
2002 case 'AnyTypeAnnotation':
2003 case 'MixedTypeAnnotation':
2004 case 'IntersectionTypeAnnotation':
2005 return null;
2006 default:
2007 return false;
2008 }
2009 }
2010
2011 /**
2012 * Returns `true` if the annotation is compatible with a string,
2013 * `false` if it definitely isn't, or `null` if we're not sure.
2014 */
2015 function maybeStringAnnotation(annotation) {
2016 switch (annotation.type) {
2017 case 'TypeAnnotation':
2018 case 'FunctionTypeParam':
2019 case 'NullableTypeAnnotation':
2020 return maybeStringAnnotation(annotation.typeAnnotation);
2021 case 'StringTypeAnnotation':
2022 return true;
2023 case 'StringLiteralTypeAnnotation':
2024 return null;
2025 case 'GenericTypeAnnotation':
2026 switch (annotation.id.name) {
2027 case 'Array':
2028 case 'Function':
2029 case 'Object':
2030 case 'Number':
2031 case 'Boolean':
2032 case 'Date':
2033 case 'RegExp':
2034 return false;
2035 default:
2036 return null;
2037 }
2038 case 'UnionTypeAnnotation':
2039 var falseCount = 0;
2040 var _iteratorNormalCompletion12 = true;
2041 var _didIteratorError12 = false;
2042 var _iteratorError12 = undefined;
2043
2044 try {
2045 for (var _iterator12 = annotation.types[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
2046 var _type6 = _step12.value;
2047
2048 var result = maybeStringAnnotation(_type6);
2049 if (result === true) {
2050 return true;
2051 } else if (result === false) {
2052 falseCount++;
2053 }
2054 }
2055 } catch (err) {
2056 _didIteratorError12 = true;
2057 _iteratorError12 = err;
2058 } finally {
2059 try {
2060 if (!_iteratorNormalCompletion12 && _iterator12.return) {
2061 _iterator12.return();
2062 }
2063 } finally {
2064 if (_didIteratorError12) {
2065 throw _iteratorError12;
2066 }
2067 }
2068 }
2069
2070 if (falseCount === annotation.types.length) {
2071 return false;
2072 } else {
2073 return null;
2074 }
2075 case 'AnyTypeAnnotation':
2076 case 'MixedTypeAnnotation':
2077 case 'IntersectionTypeAnnotation':
2078 return null;
2079 default:
2080 return false;
2081 }
2082 }
2083
2084 /**
2085 * Returns `true` if the annotation is compatible with a symbol,
2086 * `false` if it definitely isn't, or `null` if we're not sure.
2087 */
2088 function maybeSymbolAnnotation(annotation) {
2089 switch (annotation.type) {
2090 case 'TypeAnnotation':
2091 case 'FunctionTypeParam':
2092 case 'NullableTypeAnnotation':
2093 return maybeSymbolAnnotation(annotation.typeAnnotation);
2094 case 'GenericTypeAnnotation':
2095 switch (annotation.id.name) {
2096 case 'Array':
2097 case 'Function':
2098 case 'Object':
2099 case 'Number':
2100 case 'Boolean':
2101 case 'Date':
2102 case 'RegExp':
2103 return false;
2104 case 'Symbol':
2105 return true;
2106 default:
2107 return null;
2108 }
2109 case 'UnionTypeAnnotation':
2110 var falseCount = 0;
2111 var _iteratorNormalCompletion13 = true;
2112 var _didIteratorError13 = false;
2113 var _iteratorError13 = undefined;
2114
2115 try {
2116 for (var _iterator13 = annotation.types[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
2117 var _type7 = _step13.value;
2118
2119 var result = maybeSymbolAnnotation(_type7);
2120 if (result === true) {
2121 return true;
2122 } else if (result === false) {
2123 falseCount++;
2124 }
2125 }
2126 } catch (err) {
2127 _didIteratorError13 = true;
2128 _iteratorError13 = err;
2129 } finally {
2130 try {
2131 if (!_iteratorNormalCompletion13 && _iterator13.return) {
2132 _iterator13.return();
2133 }
2134 } finally {
2135 if (_didIteratorError13) {
2136 throw _iteratorError13;
2137 }
2138 }
2139 }
2140
2141 if (falseCount === annotation.types.length) {
2142 return false;
2143 } else {
2144 return null;
2145 }
2146 case 'AnyTypeAnnotation':
2147 case 'MixedTypeAnnotation':
2148 case 'IntersectionTypeAnnotation':
2149 return null;
2150 default:
2151 return false;
2152 }
2153 }
2154
2155 /**
2156 * Returns `true` if the annotation is compatible with a boolean,
2157 * `false` if it definitely isn't, or `null` if we're not sure.
2158 */
2159 function maybeBooleanAnnotation(annotation) {
2160 switch (annotation.type) {
2161 case 'TypeAnnotation':
2162 case 'FunctionTypeParam':
2163 case 'NullableTypeAnnotation':
2164 return maybeBooleanAnnotation(annotation.typeAnnotation);
2165 case 'BooleanTypeAnnotation':
2166 case 'BooleanLiteralTypeAnnotation':
2167 return true;
2168 case 'GenericTypeAnnotation':
2169 switch (annotation.id.name) {
2170 case 'Array':
2171 case 'Function':
2172 case 'Object':
2173 case 'String':
2174 case 'Number':
2175 case 'Date':
2176 case 'RegExp':
2177 return false;
2178 default:
2179 return null;
2180 }
2181 case 'UnionTypeAnnotation':
2182 var falseCount = 0;
2183 var _iteratorNormalCompletion14 = true;
2184 var _didIteratorError14 = false;
2185 var _iteratorError14 = undefined;
2186
2187 try {
2188 for (var _iterator14 = annotation.types[Symbol.iterator](), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) {
2189 var _type8 = _step14.value;
2190
2191 var result = maybeBooleanAnnotation(_type8);
2192 if (result === true) {
2193 return true;
2194 } else if (result === false) {
2195 falseCount++;
2196 }
2197 }
2198 } catch (err) {
2199 _didIteratorError14 = true;
2200 _iteratorError14 = err;
2201 } finally {
2202 try {
2203 if (!_iteratorNormalCompletion14 && _iterator14.return) {
2204 _iterator14.return();
2205 }
2206 } finally {
2207 if (_didIteratorError14) {
2208 throw _iteratorError14;
2209 }
2210 }
2211 }
2212
2213 if (falseCount === annotation.types.length) {
2214 return false;
2215 } else {
2216 return null;
2217 }
2218 case 'AnyTypeAnnotation':
2219 case 'MixedTypeAnnotation':
2220 case 'IntersectionTypeAnnotation':
2221 return null;
2222 default:
2223 return false;
2224 }
2225 }
2226
2227 /**
2228 * Returns `true` if the annotation is compatible with a function,
2229 * `false` if it definitely isn't, or `null` if we're not sure.
2230 */
2231 function maybeFunctionAnnotation(annotation) {
2232 switch (annotation.type) {
2233 case 'TypeAnnotation':
2234 case 'FunctionTypeParam':
2235 case 'NullableTypeAnnotation':
2236 return maybeFunctionAnnotation(annotation.typeAnnotation);
2237 case 'FunctionTypeAnnotation':
2238 return true;
2239 case 'GenericTypeAnnotation':
2240 switch (annotation.id.name) {
2241 case 'Array':
2242 case 'Number':
2243 case 'Object':
2244 case 'String':
2245 case 'Boolean':
2246 case 'Date':
2247 case 'RegExp':
2248 return false;
2249 default:
2250 return null;
2251 }
2252 case 'UnionTypeAnnotation':
2253 var falseCount = 0;
2254 var _iteratorNormalCompletion15 = true;
2255 var _didIteratorError15 = false;
2256 var _iteratorError15 = undefined;
2257
2258 try {
2259 for (var _iterator15 = annotation.types[Symbol.iterator](), _step15; !(_iteratorNormalCompletion15 = (_step15 = _iterator15.next()).done); _iteratorNormalCompletion15 = true) {
2260 var _type9 = _step15.value;
2261
2262 var result = maybeFunctionAnnotation(_type9);
2263 if (result === true) {
2264 return true;
2265 } else if (result === false) {
2266 falseCount++;
2267 }
2268 }
2269 } catch (err) {
2270 _didIteratorError15 = true;
2271 _iteratorError15 = err;
2272 } finally {
2273 try {
2274 if (!_iteratorNormalCompletion15 && _iterator15.return) {
2275 _iterator15.return();
2276 }
2277 } finally {
2278 if (_didIteratorError15) {
2279 throw _iteratorError15;
2280 }
2281 }
2282 }
2283
2284 if (falseCount === annotation.types.length) {
2285 return false;
2286 } else {
2287 return null;
2288 }
2289 case 'AnyTypeAnnotation':
2290 case 'MixedTypeAnnotation':
2291 case 'IntersectionTypeAnnotation':
2292 return null;
2293 default:
2294 return false;
2295 }
2296 }
2297
2298 /**
2299 * Returns `true` if the annotation is compatible with an undefined or null type,
2300 * `false` if it definitely isn't, or `null` if we're not sure.
2301 */
2302 function maybeNullableAnnotation(annotation) {
2303 switch (annotation.type) {
2304 case 'NullableTypeAnnotation':
2305 case 'VoidTypeAnnotation':
2306 case 'MixedTypeAnnotation':
2307 return true;
2308 case 'TypeAnnotation':
2309 case 'FunctionTypeParam':
2310 return maybeNullableAnnotation(annotation.typeAnnotation);
2311 case 'GenericTypeAnnotation':
2312 switch (annotation.id.name) {
2313 case 'Array':
2314 case 'Number':
2315 case 'Object':
2316 case 'String':
2317 case 'Boolean':
2318 case 'Date':
2319 case 'RegExp':
2320 return false;
2321 case 'Generator':
2322 if (annotation.typeParameters && annotation.typeParameters.params.length > 1) {
2323 return maybeNullableAnnotation(annotation.typeParameters.params[1]);
2324 } else {
2325 return null;
2326 }
2327 default:
2328 return null;
2329 }
2330 case 'UnionTypeAnnotation':
2331 var falseCount = 0;
2332 var _iteratorNormalCompletion16 = true;
2333 var _didIteratorError16 = false;
2334 var _iteratorError16 = undefined;
2335
2336 try {
2337 for (var _iterator16 = annotation.types[Symbol.iterator](), _step16; !(_iteratorNormalCompletion16 = (_step16 = _iterator16.next()).done); _iteratorNormalCompletion16 = true) {
2338 var _type10 = _step16.value;
2339
2340 var result = maybeNullableAnnotation(_type10);
2341 if (result === true) {
2342 return true;
2343 } else if (result === false) {
2344 falseCount++;
2345 }
2346 }
2347 } catch (err) {
2348 _didIteratorError16 = true;
2349 _iteratorError16 = err;
2350 } finally {
2351 try {
2352 if (!_iteratorNormalCompletion16 && _iterator16.return) {
2353 _iterator16.return();
2354 }
2355 } finally {
2356 if (_didIteratorError16) {
2357 throw _iteratorError16;
2358 }
2359 }
2360 }
2361
2362 if (falseCount === annotation.types.length) {
2363 return false;
2364 } else {
2365 return null;
2366 }
2367 default:
2368 return false;
2369 }
2370 }
2371
2372 /**
2373 * Returns `true` if the annotation is compatible with an object type,
2374 * `false` if it definitely isn't, or `null` if we're not sure.
2375 */
2376 function maybeInstanceOfAnnotation(annotation, expected, typeParameters) {
2377 switch (annotation.type) {
2378 case 'TypeAnnotation':
2379 case 'FunctionTypeParam':
2380 case 'NullableTypeAnnotation':
2381 return maybeInstanceOfAnnotation(annotation.typeAnnotation, expected, typeParameters);
2382 case 'GenericTypeAnnotation':
2383 if (annotation.id.name === expected.name) {
2384 if (typeParameters.length === 0) {
2385 return true;
2386 }
2387 if (annotation.typeParameters && annotation.typeParameters.params.length) {
2388 var trueCount = 0;
2389 var nullCount = 0;
2390 for (var i = 0; i < typeParameters.length && i < annotation.typeParameters.params.length; i++) {
2391 var result = compareAnnotations(typeParameters[i], annotation.typeParameters.params[i]);
2392 if (result === false) {
2393 return false;
2394 } else if (result === true) {
2395 trueCount++;
2396 } else {
2397 nullCount++;
2398 }
2399 }
2400 return trueCount > 0 && nullCount === 0 ? true : null;
2401 }
2402 }
2403 return null;
2404 case 'UnionTypeAnnotation':
2405 var falseCount = 0;
2406 var _iteratorNormalCompletion17 = true;
2407 var _didIteratorError17 = false;
2408 var _iteratorError17 = undefined;
2409
2410 try {
2411 for (var _iterator17 = annotation.types[Symbol.iterator](), _step17; !(_iteratorNormalCompletion17 = (_step17 = _iterator17.next()).done); _iteratorNormalCompletion17 = true) {
2412 var _type11 = _step17.value;
2413
2414 var result = maybeInstanceOfAnnotation(_type11, expected, typeParameters);
2415 if (result === true) {
2416 return true;
2417 } else if (result === false) {
2418 falseCount++;
2419 }
2420 }
2421 } catch (err) {
2422 _didIteratorError17 = true;
2423 _iteratorError17 = err;
2424 } finally {
2425 try {
2426 if (!_iteratorNormalCompletion17 && _iterator17.return) {
2427 _iterator17.return();
2428 }
2429 } finally {
2430 if (_didIteratorError17) {
2431 throw _iteratorError17;
2432 }
2433 }
2434 }
2435
2436 if (falseCount === annotation.types.length) {
2437 return false;
2438 } else {
2439 return null;
2440 }
2441 case 'VoidTypeAnnotation':
2442 case 'BooleanTypeAnnotation':
2443 case 'BooleanLiteralTypeAnnotation':
2444 case 'StringTypeAnnotation':
2445 case 'StringLiteralTypeAnnotation':
2446 case 'NumberTypeAnnotation':
2447 case 'NumericLiteralTypeAnnotation':
2448 case 'FunctionTypeAnnotation':
2449 return false;
2450 default:
2451 return null;
2452 }
2453 }
2454
2455 /**
2456 * Returns `true` if the annotation is compatible with an array,
2457 * `false` if it definitely isn't, or `null` if we're not sure.
2458 */
2459 function maybeArrayAnnotation(annotation) {
2460 switch (annotation.type) {
2461 case 'TypeAnnotation':
2462 case 'FunctionTypeParam':
2463 case 'NullableTypeAnnotation':
2464 return maybeArrayAnnotation(annotation.typeAnnotation);
2465 case 'TupleTypeAnnotation':
2466 case 'ArrayTypeAnnotation':
2467 return true;
2468 case 'GenericTypeAnnotation':
2469 return annotation.id.name === 'Array' ? true : null;
2470 case 'UnionTypeAnnotation':
2471 var falseCount = 0;
2472 var _iteratorNormalCompletion18 = true;
2473 var _didIteratorError18 = false;
2474 var _iteratorError18 = undefined;
2475
2476 try {
2477 for (var _iterator18 = annotation.types[Symbol.iterator](), _step18; !(_iteratorNormalCompletion18 = (_step18 = _iterator18.next()).done); _iteratorNormalCompletion18 = true) {
2478 var _type12 = _step18.value;
2479
2480 var result = maybeArrayAnnotation(_type12);
2481 if (result === true) {
2482 return true;
2483 } else if (result === false) {
2484 falseCount++;
2485 }
2486 }
2487 } catch (err) {
2488 _didIteratorError18 = true;
2489 _iteratorError18 = err;
2490 } finally {
2491 try {
2492 if (!_iteratorNormalCompletion18 && _iterator18.return) {
2493 _iterator18.return();
2494 }
2495 } finally {
2496 if (_didIteratorError18) {
2497 throw _iteratorError18;
2498 }
2499 }
2500 }
2501
2502 if (falseCount === annotation.types.length) {
2503 return false;
2504 } else {
2505 return null;
2506 }
2507 case 'AnyTypeAnnotation':
2508 case 'MixedTypeAnnotation':
2509 case 'IntersectionTypeAnnotation':
2510 return null;
2511 default:
2512 return false;
2513 }
2514 }
2515
2516 /**
2517 * Returns `true` if the annotation is compatible with an iterable,
2518 * `false` if it definitely isn't, or `null` if we're not sure.
2519 */
2520 function maybeIterableAnnotation(annotation) {
2521 switch (annotation.type) {
2522 case 'TypeAnnotation':
2523 case 'FunctionTypeParam':
2524 case 'NullableTypeAnnotation':
2525 return maybeIterableAnnotation(annotation.typeAnnotation);
2526 case 'TupleTypeAnnotation':
2527 case 'ArrayTypeAnnotation':
2528 return true;
2529 case 'GenericTypeAnnotation':
2530 return annotation.id.name === 'Iterable' ? true : null;
2531 case 'UnionTypeAnnotation':
2532 var falseCount = 0;
2533 var _iteratorNormalCompletion19 = true;
2534 var _didIteratorError19 = false;
2535 var _iteratorError19 = undefined;
2536
2537 try {
2538 for (var _iterator19 = annotation.types[Symbol.iterator](), _step19; !(_iteratorNormalCompletion19 = (_step19 = _iterator19.next()).done); _iteratorNormalCompletion19 = true) {
2539 var _type13 = _step19.value;
2540
2541 var result = maybeIterableAnnotation(_type13);
2542 if (result === true) {
2543 return true;
2544 } else if (result === false) {
2545 falseCount++;
2546 }
2547 }
2548 } catch (err) {
2549 _didIteratorError19 = true;
2550 _iteratorError19 = err;
2551 } finally {
2552 try {
2553 if (!_iteratorNormalCompletion19 && _iterator19.return) {
2554 _iterator19.return();
2555 }
2556 } finally {
2557 if (_didIteratorError19) {
2558 throw _iteratorError19;
2559 }
2560 }
2561 }
2562
2563 if (falseCount === annotation.types.length) {
2564 return false;
2565 } else {
2566 return null;
2567 }
2568 case 'BooleanTypeAnnotation':
2569 case 'BooleanLiteralTypeAnnotation':
2570 case 'NumericLiteralTypeAnnotation':
2571 case 'NumberTypeAnnotation':
2572 case 'VoidTypeAnnotation':
2573 return false;
2574 default:
2575 return null;
2576 }
2577 }
2578
2579 /**
2580 * Returns `true` if the annotation is compatible with a tuple,
2581 * `false` if it definitely isn't, or `null` if we're not sure.
2582 */
2583 function maybeTupleAnnotation(annotation) {
2584 switch (annotation.type) {
2585 case 'TypeAnnotation':
2586 case 'FunctionTypeParam':
2587 case 'NullableTypeAnnotation':
2588 return maybeTupleAnnotation(annotation.typeAnnotation);
2589 case 'TupleTypeAnnotation':
2590 return true;
2591 case 'UnionTypeAnnotation':
2592 var falseCount = 0;
2593 var _iteratorNormalCompletion20 = true;
2594 var _didIteratorError20 = false;
2595 var _iteratorError20 = undefined;
2596
2597 try {
2598 for (var _iterator20 = annotation.types[Symbol.iterator](), _step20; !(_iteratorNormalCompletion20 = (_step20 = _iterator20.next()).done); _iteratorNormalCompletion20 = true) {
2599 var _type14 = _step20.value;
2600
2601 var result = maybeTupleAnnotation(_type14);
2602 if (result === true) {
2603 return true;
2604 } else if (result === false) {
2605 falseCount++;
2606 }
2607 }
2608 } catch (err) {
2609 _didIteratorError20 = true;
2610 _iteratorError20 = err;
2611 } finally {
2612 try {
2613 if (!_iteratorNormalCompletion20 && _iterator20.return) {
2614 _iterator20.return();
2615 }
2616 } finally {
2617 if (_didIteratorError20) {
2618 throw _iteratorError20;
2619 }
2620 }
2621 }
2622
2623 if (falseCount === annotation.types.length) {
2624 return false;
2625 } else {
2626 return null;
2627 }
2628 case 'GenericTypeAnnotation':
2629 case 'AnyTypeAnnotation':
2630 case 'ArrayTypeAnnotation':
2631 case 'MixedTypeAnnotation':
2632 case 'IntersectionTypeAnnotation':
2633 return null;
2634 default:
2635 return false;
2636 }
2637 }
2638
2639 function humanReadableType(annotation) {
2640 switch (annotation.type) {
2641 case 'TypeAnnotation':
2642 case 'FunctionTypeParam':
2643 return humanReadableType(annotation.typeAnnotation);
2644
2645 case 'FunctionTypeAnnotation':
2646 // @fixme babel doesn't seem to like generating FunctionTypeAnnotations yet
2647 return '(' + annotation.params.map(humanReadableType).join(', ') + ') => ' + humanReadableType(annotation.returnType);
2648 default:
2649 return (0, _babelGenerator2.default)(annotation).code;
2650 }
2651 }
2652
2653 function getTypeChecker(id, scope) {
2654 var binding = scope.getBinding(id.name);
2655 if (binding === undefined) {
2656 return false;
2657 }
2658 var path = binding.path;
2659
2660 if (path == null) {
2661 return false;
2662 } else if (path.type === 'TypeAlias') {
2663 return path;
2664 } else if (path.type === 'VariableDeclaration' && path.node.isTypeChecker) {
2665 return path.get('declarations')[0];
2666 } else if (path.isImportSpecifier() && path.parent.importKind === 'type') {
2667 return path;
2668 }
2669 return false;
2670 }
2671
2672 function isTypeChecker(id, scope) {
2673 var binding = scope.getBinding(id.name);
2674 if (binding === undefined) {
2675 return false;
2676 }
2677 var path = binding.path;
2678
2679 if (path == null) {
2680 return false;
2681 } else if (path.type === 'TypeAlias' || path.type === 'VariableDeclaration' && path.node.isTypeChecker) {
2682 return true;
2683 } else if (path.isImportSpecifier() && path.parent.importKind === 'type') {
2684 return true;
2685 }
2686 return false;
2687 }
2688
2689 function isPolymorphicType(id, scope) {
2690 var binding = scope.getBinding(id.name);
2691 if (binding !== undefined) {
2692 return false;
2693 }
2694 var path = scope.path;
2695
2696 while (path && path.type !== 'Program') {
2697 var _path = path;
2698 var _node = _path.node;
2699
2700 if ((t.isFunction(_node) || t.isClass(_node)) && _node.typeParameters) {
2701 var _iteratorNormalCompletion21 = true;
2702 var _didIteratorError21 = false;
2703 var _iteratorError21 = undefined;
2704
2705 try {
2706 for (var _iterator21 = _node.typeParameters.params[Symbol.iterator](), _step21; !(_iteratorNormalCompletion21 = (_step21 = _iterator21.next()).done); _iteratorNormalCompletion21 = true) {
2707 var param = _step21.value;
2708
2709 param.isPolymorphicType = true;
2710 if (param.name === id.name) {
2711 return true;
2712 }
2713 }
2714 } catch (err) {
2715 _didIteratorError21 = true;
2716 _iteratorError21 = err;
2717 } finally {
2718 try {
2719 if (!_iteratorNormalCompletion21 && _iterator21.return) {
2720 _iterator21.return();
2721 }
2722 } finally {
2723 if (_didIteratorError21) {
2724 throw _iteratorError21;
2725 }
2726 }
2727 }
2728 }
2729 path = path.parentPath;
2730 }
2731 return false;
2732 }
2733
2734 function getPolymorphicType(id, scope) {
2735 var binding = scope.getBinding(id.name);
2736 if (binding !== undefined) {
2737 return false;
2738 }
2739 var path = scope.path;
2740
2741 while (path && path.type !== 'Program') {
2742 var _path2 = path;
2743 var _node2 = _path2.node;
2744
2745 if (t.isFunction(_node2) && _node2.typeParameters) {
2746 var _iteratorNormalCompletion22 = true;
2747 var _didIteratorError22 = false;
2748 var _iteratorError22 = undefined;
2749
2750 try {
2751 for (var _iterator22 = _node2.typeParameters.params[Symbol.iterator](), _step22; !(_iteratorNormalCompletion22 = (_step22 = _iterator22.next()).done); _iteratorNormalCompletion22 = true) {
2752 var param = _step22.value;
2753
2754 param.isPolymorphicType = true;
2755 if (param.name === id.name) {
2756 return param;
2757 }
2758 }
2759 } catch (err) {
2760 _didIteratorError22 = true;
2761 _iteratorError22 = err;
2762 } finally {
2763 try {
2764 if (!_iteratorNormalCompletion22 && _iterator22.return) {
2765 _iterator22.return();
2766 }
2767 } finally {
2768 if (_didIteratorError22) {
2769 throw _iteratorError22;
2770 }
2771 }
2772 }
2773 }
2774 path = path.parent;
2775 }
2776 return null;
2777 }
2778
2779 function collectParamChecks(path) {
2780 return path.get('params').map(function (param) {
2781 var node = param.node;
2782
2783 if (node.type === 'AssignmentPattern') {
2784 if (node.left.typeAnnotation) {
2785 return createDefaultParamGuard(param);
2786 }
2787 } else if (node.type === 'RestElement') {
2788 if (node.typeAnnotation) {
2789 return createRestParamGuard(param);
2790 }
2791 } else if (node.typeAnnotation) {
2792 return createParamGuard(param);
2793 }
2794 }).filter(identity);
2795 }
2796
2797 function createParamGuard(path) {
2798 var node = path.node;
2799 var scope = path.scope;
2800
2801 node.hasBeenTypeChecked = true;
2802 node.savedTypeAnnotation = node.typeAnnotation;
2803 if (node.type === 'ObjectPattern') {
2804 return;
2805 }
2806 var check = checkAnnotation(node, node.typeAnnotation, scope);
2807 if (!check) {
2808 return;
2809 }
2810 if (node.optional) {
2811 check = t.logicalExpression('||', checks.undefined({ input: node }), check);
2812 }
2813 var message = paramTypeErrorMessage(node, scope);
2814 return guard({
2815 check: check,
2816 message: message
2817 });
2818 }
2819
2820 function createDefaultParamGuard(path) {
2821 var node = path.node;
2822 var scope = path.scope;
2823 var id = node.left;
2824 var value = node.right;
2825
2826 var ok = staticCheckAnnotation(path.get('right'), id.typeAnnotation);
2827 if (ok === false) {
2828 throw path.buildCodeFrameError('Invalid default value for argument "' + id.name + '", expected ' + humanReadableType(id.typeAnnotation) + '.');
2829 }
2830 return createParamGuard(path.get('left'));
2831 }
2832
2833 function createRestParamGuard(path) {
2834 var node = path.node;
2835 var scope = path.scope;
2836 var id = node.argument;
2837
2838 id.hasBeenTypeChecked = true;
2839 node.savedTypeAnnotation = node.typeAnnotation;
2840 if (!isStrictlyArrayAnnotation(node.typeAnnotation)) {
2841 throw path.buildCodeFrameError('Invalid type annotation for rest argument "' + id.name + '", expected an Array, got: ' + humanReadableType(node.typeAnnotation) + '.');
2842 }
2843 var check = checkAnnotation(id, node.typeAnnotation, scope);
2844 if (!check) {
2845 return;
2846 }
2847 if (node.optional) {
2848 check = t.logicalExpression('||', checks.undefined({ input: id }), check);
2849 }
2850 var message = paramTypeErrorMessage(id, scope, node.typeAnnotation);
2851 return guard({
2852 check: check,
2853 message: message
2854 });
2855 }
2856
2857 function returnTypeErrorMessage(path, fn, id) {
2858 var node = path.node;
2859 var scope = path.scope;
2860
2861 var name = fn.id ? fn.id.name : '';
2862 var annotation = fn.returnType;
2863 if (annotation.type === 'TypeAnnotation') {
2864 annotation = annotation.typeAnnotation;
2865 }
2866 if (fn.generator && isGeneratorAnnotation(annotation) && annotation.typeParameters && annotation.typeParameters.params.length > 1) {
2867 annotation = annotation.typeParameters.params[1];
2868 }
2869 var message = 'Function ' + (name ? '"' + name + '" ' : '') + 'return value violates contract, expected ' + humanReadableType(annotation) + ' got ';
2870
2871 return t.binaryExpression('+', t.stringLiteral(message), id ? readableName({ input: id }) : node.argument ? readableName({ input: node.argument }) : t.stringLiteral('undefined'));
2872 }
2873
2874 function yieldTypeErrorMessage(path, fn, id) {
2875 var node = path.node;
2876 var scope = path.scope;
2877
2878 var name = fn.id ? fn.id.name : '';
2879 var annotation = fn.returnType;
2880 if (annotation.type === 'TypeAnnotation') {
2881 annotation = annotation.typeAnnotation;
2882 }
2883 if (fn.generator && isGeneratorAnnotation(annotation) && annotation.typeParameters && annotation.typeParameters.params.length > 0) {
2884 annotation = annotation.typeParameters.params[0];
2885 }
2886 var message = 'Function ' + (name ? '"' + name + '" ' : '') + ' yielded an invalid value, expected ' + humanReadableType(annotation) + ' got ';
2887
2888 return t.binaryExpression('+', t.stringLiteral(message), node.argument ? readableName({ input: id || node.argument }) : t.stringLiteral('undefined'));
2889 }
2890 function yieldNextTypeErrorMessage(path, fn, id) {
2891 var node = path.node;
2892 var scope = path.scope;
2893
2894 var name = fn.id ? fn.id.name : '';
2895 var annotation = fn.returnType;
2896 if (annotation.type === 'TypeAnnotation') {
2897 annotation = annotation.typeAnnotation;
2898 }
2899 if (fn.generator && isGeneratorAnnotation(annotation) && annotation.typeParameters && annotation.typeParameters.params.length > 2) {
2900 annotation = annotation.typeParameters.params[2];
2901 }
2902 var message = 'Generator ' + (name ? '"' + name + '" ' : '') + 'received an invalid next value, expected ' + humanReadableType(annotation) + ' got ';
2903
2904 return t.binaryExpression('+', t.stringLiteral(message), node.argument ? readableName({ input: id || node.argument }) : t.stringLiteral('undefined'));
2905 }
2906
2907 function paramTypeErrorMessage(node, scope) {
2908 var typeAnnotation = arguments.length <= 2 || arguments[2] === undefined ? node.typeAnnotation : arguments[2];
2909
2910 var name = node.name;
2911 var message = 'Value of ' + (node.optional ? 'optional ' : '') + 'argument "' + name + '" violates contract, expected ' + humanReadableType(typeAnnotation) + ' got ';
2912
2913 return t.binaryExpression('+', t.stringLiteral(message), readableName({ input: node }));
2914 }
2915
2916 function varTypeErrorMessage(node, scope) {
2917 var annotation = arguments.length <= 2 || arguments[2] === undefined ? node.typeAnnotation : arguments[2];
2918
2919 if (node.type === 'Identifier') {
2920 var _name2 = node.name;
2921 var message = 'Value of variable "' + _name2 + '" violates contract, expected ' + humanReadableType(annotation) + ' got ';
2922 return t.binaryExpression('+', t.stringLiteral(message), readableName({ input: node }));
2923 } else {
2924 var message = 'Value of "' + (0, _babelGenerator2.default)(node).code + '" violates contract, expected ' + humanReadableType(annotation) + ' got ';
2925 return t.binaryExpression('+', t.stringLiteral(message), readableName({ input: node }));
2926 }
2927 }
2928
2929 /**
2930 * Determine whether the given node can produce purely boolean results.
2931 */
2932 function isBooleanExpression(node) {
2933 if (node.type === 'BinaryExpression' && BOOLEAN_BINARY_OPERATORS.indexOf(node.operator) > -1) {
2934 return true;
2935 } else if (node.type === 'LogicalExpression') {
2936 return isBooleanExpression(node.left) && isBooleanExpression(node.right);
2937 } else {
2938 return false;
2939 }
2940 }
2941
2942 /**
2943 * Convert type specifier to expression.
2944 */
2945 function createTypeExpression(node) {
2946 if (node.type == 'Identifier') {
2947 return node;
2948 } else if (node.type == 'QualifiedTypeIdentifier') {
2949 return t.memberExpression(createTypeExpression(node.qualification), createTypeExpression(node.id));
2950 }
2951
2952 throw this.errorWithNode('Unsupported type: ' + node.type);
2953 }
2954
2955 /**
2956 * Get name of a type as a string.
2957 */
2958 function getTypeName(node) {
2959 if (node.type == 'Identifier') {
2960 return node.name;
2961 } else if (node.type == 'QualifiedTypeIdentifier') {
2962 return getTypeName(node.qualification) + '.' + getTypeName(node.id);
2963 }
2964
2965 throw this.errorWithNode('Unsupported type: ' + node.type);
2966 }
2967
2968 /**
2969 * Union two arrays.
2970 */
2971 function union(arr1, arr2) {
2972 for (var i = 0; i < arr2.length; i++) {
2973 var item = arr2[i];
2974 if (arr1.indexOf(item) === -1) {
2975 arr1.push(item);
2976 }
2977 }
2978 return arr1;
2979 }
2980
2981 /**
2982 * Determine whether the given annotation allows any value.
2983 */
2984 function allowsAny(annotation) {
2985 if (annotation.type === 'TypeAnnotation' || annotation.type === 'NullableTypeAnnotation') {
2986 return allowsAny(annotation.typeAnnotation);
2987 } else if (annotation.type === 'AnyTypeAnnotation' || annotation.type === 'MixedTypeAnnotation') {
2988 return true;
2989 } else if (annotation.type === 'UnionTypeAnnotation') {
2990 return annotation.types.some(allowsAny);
2991 } else {
2992 return false;
2993 }
2994 }
2995
2996 /**
2997 * Determine whether a given node is nully (null or undefined).
2998 */
2999 function isNodeNully(node) {
3000 if (node == null) {
3001 return true;
3002 } else if (node.type === 'Identifier' && node.name === 'undefined') {
3003 return true;
3004 } else if (node.type === 'Literal' && node.value === null) {
3005 return true;
3006 } else if (node.type === 'UnaryExpression' && node.operator === 'void') {
3007 return true;
3008 } else {
3009 return false;
3010 }
3011 }
3012
3013 /**
3014 * Determine whether the file should be skipped, based on the comments attached to the given node.
3015 */
3016 function maybeSkipFile(path) {
3017 if (path.node.leadingComments && path.node.leadingComments.length) {
3018 return path.node.leadingComments.some(function (comment) {
3019 return PRAGMA_IGNORE_FILE.test(comment.value);
3020 });
3021 }
3022 return false;
3023 }
3024
3025 /**
3026 * Maybe skip the given path if it has a relevant pragma.
3027 */
3028 function maybeSkip(path) {
3029 var node = path.node;
3030
3031 if (node.hasBeenTypeChecked) {
3032 return true;
3033 }
3034 if (node.leadingComments && node.leadingComments.length) {
3035 var comment = node.leadingComments[node.leadingComments.length - 1];
3036 if (PRAGMA_IGNORE_STATEMENT.test(comment.value)) {
3037 path.skip();
3038 return true;
3039 }
3040 }
3041 return false;
3042 }
3043
3044 /**
3045 * A function that returns its first argument, useful when filtering.
3046 */
3047 function identity(input) {
3048 return input;
3049 }
3050
3051 function getExpression(node) {
3052 return t.isExpressionStatement(node) ? node.expression : node;
3053 }
3054
3055 function expression(input) {
3056 var fn = template(input);
3057 return function () {
3058 var node = fn.apply(undefined, arguments);
3059 return getExpression(node);
3060 };
3061 }
3062};
3063
3064var _babelGenerator = require('babel-generator');
3065
3066var _babelGenerator2 = _interopRequireDefault(_babelGenerator);
3067
3068function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
3069
3070function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
\No newline at end of file