UNPKG

9.07 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = function (d, b) {
4 extendStatics = Object.setPrototypeOf ||
5 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7 return extendStatics(d, b);
8 }
9 return function (d, b) {
10 extendStatics(d, b);
11 function __() { this.constructor = d; }
12 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13 };
14})();
15Object.defineProperty(exports, "__esModule", { value: true });
16var ts = require("typescript");
17var Lint = require("tslint");
18var tsutils = require("tsutils");
19var AstUtils_1 = require("./utils/AstUtils");
20var Rule = (function (_super) {
21 __extends(Rule, _super);
22 function Rule() {
23 return _super !== null && _super.apply(this, arguments) || this;
24 }
25 Rule.prototype.apply = function (sourceFile) {
26 if (Rule.isWarningShown === false) {
27 console.warn('Warning: no-unnecessary-bind rule is deprecated. Replace your usage with the TSLint unnecessary-bind rule.');
28 Rule.isWarningShown = true;
29 }
30 return this.applyWithFunction(sourceFile, walk);
31 };
32 Rule.metadata = {
33 ruleName: 'no-unnecessary-bind',
34 type: 'maintainability',
35 description: 'Do not bind `this` as the context for a function literal or lambda expression.',
36 options: null,
37 optionsDescription: '',
38 typescriptOnly: true,
39 issueClass: 'Non-SDL',
40 issueType: 'Warning',
41 severity: 'Important',
42 level: 'Opportunity for Excellence',
43 recommendation: 'false',
44 group: 'Correctness',
45 commonWeaknessEnumeration: '398, 710'
46 };
47 Rule.FAILURE_FUNCTION_WITH_BIND = "Binding function literal with 'this' context. Use lambdas instead";
48 Rule.FAILURE_ARROW_WITH_BIND = "Binding lambda with 'this' context. Lambdas already have 'this' bound";
49 Rule.UNDERSCORE_BINARY_FUNCTION_NAMES = [
50 'all',
51 'any',
52 'collect',
53 'countBy',
54 'detect',
55 'each',
56 'every',
57 'filter',
58 'find',
59 'forEach',
60 'groupBy',
61 'indexBy',
62 'map',
63 'max',
64 'max',
65 'min',
66 'partition',
67 'reject',
68 'select',
69 'some',
70 'sortBy',
71 'times',
72 'uniq',
73 'unique'
74 ];
75 Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES = ['foldl', 'foldr', 'inject', 'reduce', 'reduceRight'];
76 Rule.isWarningShown = false;
77 return Rule;
78}(Lint.Rules.AbstractRule));
79exports.Rule = Rule;
80function walk(ctx) {
81 function cb(node) {
82 if (tsutils.isCallExpression(node)) {
83 var analyzers = [
84 new TypeScriptFunctionAnalyzer(),
85 new UnderscoreStaticAnalyzer(),
86 new UnderscoreInstanceAnalyzer()
87 ];
88 analyzers.forEach(function (analyzer) {
89 if (analyzer.canHandle(node)) {
90 var contextArgument = analyzer.getContextArgument(node);
91 var functionArgument = analyzer.getFunctionArgument(node);
92 if (contextArgument === undefined || functionArgument === undefined) {
93 return;
94 }
95 if (contextArgument.getText() === 'this') {
96 if (isArrowFunction(functionArgument)) {
97 ctx.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_ARROW_WITH_BIND);
98 }
99 else if (isFunctionLiteral(functionArgument)) {
100 ctx.addFailureAt(node.getStart(), node.getWidth(), Rule.FAILURE_FUNCTION_WITH_BIND);
101 }
102 }
103 }
104 });
105 }
106 return ts.forEachChild(node, cb);
107 }
108 return ts.forEachChild(ctx.sourceFile, cb);
109}
110var TypeScriptFunctionAnalyzer = (function () {
111 function TypeScriptFunctionAnalyzer() {
112 }
113 TypeScriptFunctionAnalyzer.prototype.canHandle = function (node) {
114 return !!(AstUtils_1.AstUtils.getFunctionName(node) === 'bind' &&
115 node.arguments.length === 1 &&
116 node.expression.kind === ts.SyntaxKind.PropertyAccessExpression);
117 };
118 TypeScriptFunctionAnalyzer.prototype.getContextArgument = function (node) {
119 return node.arguments[0];
120 };
121 TypeScriptFunctionAnalyzer.prototype.getFunctionArgument = function (node) {
122 return node.expression.expression;
123 };
124 return TypeScriptFunctionAnalyzer;
125}());
126var UnderscoreStaticAnalyzer = (function () {
127 function UnderscoreStaticAnalyzer() {
128 }
129 UnderscoreStaticAnalyzer.prototype.canHandle = function (node) {
130 var isUnderscore = AstUtils_1.AstUtils.getFunctionTarget(node) === '_';
131 if (isUnderscore) {
132 var functionName = AstUtils_1.AstUtils.getFunctionName(node);
133 if (functionName === 'bind') {
134 return node.arguments.length === 2;
135 }
136 }
137 return isUnderscore;
138 };
139 UnderscoreStaticAnalyzer.prototype.getContextArgument = function (node) {
140 var functionName = AstUtils_1.AstUtils.getFunctionName(node);
141 if (Rule.UNDERSCORE_BINARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
142 return node.arguments[2];
143 }
144 else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
145 return node.arguments[3];
146 }
147 else if (functionName === 'sortedIndex') {
148 return node.arguments[3];
149 }
150 else if (functionName === 'bind') {
151 return node.arguments[1];
152 }
153 return undefined;
154 };
155 UnderscoreStaticAnalyzer.prototype.getFunctionArgument = function (node) {
156 var functionName = AstUtils_1.AstUtils.getFunctionName(node);
157 if (Rule.UNDERSCORE_BINARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
158 return node.arguments[1];
159 }
160 else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
161 return node.arguments[1];
162 }
163 else if (functionName === 'sortedIndex') {
164 return node.arguments[2];
165 }
166 else if (functionName === 'bind') {
167 return node.arguments[0];
168 }
169 return undefined;
170 };
171 return UnderscoreStaticAnalyzer;
172}());
173var UnderscoreInstanceAnalyzer = (function () {
174 function UnderscoreInstanceAnalyzer() {
175 }
176 UnderscoreInstanceAnalyzer.prototype.canHandle = function (node) {
177 if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
178 var propExpression = node.expression;
179 if (propExpression.expression.kind === ts.SyntaxKind.CallExpression) {
180 var call = propExpression.expression;
181 return call.expression.getText() === '_';
182 }
183 }
184 return false;
185 };
186 UnderscoreInstanceAnalyzer.prototype.getContextArgument = function (node) {
187 var functionName = AstUtils_1.AstUtils.getFunctionName(node);
188 if (Rule.UNDERSCORE_BINARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
189 return node.arguments[1];
190 }
191 else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
192 return node.arguments[2];
193 }
194 else if (functionName === 'sortedIndex') {
195 return node.arguments[2];
196 }
197 return undefined;
198 };
199 UnderscoreInstanceAnalyzer.prototype.getFunctionArgument = function (node) {
200 var functionName = AstUtils_1.AstUtils.getFunctionName(node);
201 if (Rule.UNDERSCORE_BINARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
202 return node.arguments[0];
203 }
204 else if (Rule.UNDERSCORE_TERNARY_FUNCTION_NAMES.indexOf(functionName) !== -1) {
205 return node.arguments[0];
206 }
207 else if (functionName === 'sortedIndex') {
208 return node.arguments[1];
209 }
210 return undefined;
211 };
212 return UnderscoreInstanceAnalyzer;
213}());
214function isFunctionLiteral(expression) {
215 if (expression.kind === ts.SyntaxKind.FunctionExpression) {
216 return true;
217 }
218 if (expression.kind === ts.SyntaxKind.ParenthesizedExpression) {
219 return isFunctionLiteral(expression.expression);
220 }
221 return false;
222}
223function isArrowFunction(expression) {
224 if (expression.kind === ts.SyntaxKind.ArrowFunction) {
225 return true;
226 }
227 if (expression.kind === ts.SyntaxKind.ParenthesizedExpression) {
228 return isArrowFunction(expression.expression);
229 }
230 return false;
231}
232//# sourceMappingURL=noUnnecessaryBindRule.js.map
\No newline at end of file