1 | var __extends = (this && this.__extends) || function (d, b) {
|
2 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
3 | function __() { this.constructor = d; }
|
4 | __.prototype = b.prototype;
|
5 | d.prototype = new __();
|
6 | };
|
7 | var ErrorTolerantWalker = require('./utils/ErrorTolerantWalker');
|
8 | var SyntaxKind = require('./utils/SyntaxKind');
|
9 | var Utils = require('./utils/Utils');
|
10 | var Rule = (function (_super) {
|
11 | __extends(Rule, _super);
|
12 | function Rule() {
|
13 | _super.apply(this, arguments);
|
14 | }
|
15 | Rule.prototype.apply = function (sourceFile) {
|
16 | return this.applyWithWalker(new ValidTypeofRuleWalker(sourceFile, this.getOptions()));
|
17 | };
|
18 | Rule.FAILURE_STRING = 'Invalid comparison in typeof. Did you mean ';
|
19 | Rule.VALID_TERMS = ['undefined', 'object', 'boolean', 'number', 'string', 'function'];
|
20 | return Rule;
|
21 | })(Lint.Rules.AbstractRule);
|
22 | exports.Rule = Rule;
|
23 | var ValidTypeofRuleWalker = (function (_super) {
|
24 | __extends(ValidTypeofRuleWalker, _super);
|
25 | function ValidTypeofRuleWalker() {
|
26 | _super.apply(this, arguments);
|
27 | }
|
28 | ValidTypeofRuleWalker.prototype.visitBinaryExpression = function (node) {
|
29 | if (node.left.kind === SyntaxKind.current().TypeOfExpression && node.right.kind === SyntaxKind.current().StringLiteral) {
|
30 | this.validateTypeOf(node.right);
|
31 | }
|
32 | else if (node.right.kind === SyntaxKind.current().TypeOfExpression && node.left.kind === SyntaxKind.current().StringLiteral) {
|
33 | this.validateTypeOf(node.left);
|
34 | }
|
35 | _super.prototype.visitBinaryExpression.call(this, node);
|
36 | };
|
37 | ValidTypeofRuleWalker.prototype.validateTypeOf = function (node) {
|
38 | if (Rule.VALID_TERMS.indexOf(node.text) === -1) {
|
39 | var start = node.getStart();
|
40 | var width = node.getWidth();
|
41 | this.addFailure(this.createFailure(start, width, Rule.FAILURE_STRING + this.getClosestTerm(node.text) + '?'));
|
42 | }
|
43 | };
|
44 | ValidTypeofRuleWalker.prototype.getClosestTerm = function (term) {
|
45 | var _this = this;
|
46 | var closestMatch = 99999999;
|
47 | return Utils.reduce(Rule.VALID_TERMS, function (closestTerm, thisTerm) {
|
48 | var distance = _this.hammingDistance(term, thisTerm);
|
49 | if (distance < closestMatch) {
|
50 | closestMatch = distance;
|
51 | closestTerm = thisTerm;
|
52 | }
|
53 | return closestTerm;
|
54 | }, '');
|
55 | };
|
56 | ValidTypeofRuleWalker.prototype.hammingDistance = function (source, target) {
|
57 | if (source.length === 0) {
|
58 | return target.length;
|
59 | }
|
60 | if (target.length === 0) {
|
61 | return source.length;
|
62 | }
|
63 | return Math.min(this.hammingDistance(source.substr(1), target) + 1, this.hammingDistance(target.substr(1), source) + 1, this.hammingDistance(source.substr(1), target.substr(1)) + (source[0] !== target[0] ? 1 : 0)) + 1;
|
64 | };
|
65 | return ValidTypeofRuleWalker;
|
66 | })(ErrorTolerantWalker);
|
67 |
|
\ | No newline at end of file |