1 | "use strict";
|
2 | var __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 | })();
|
15 | Object.defineProperty(exports, "__esModule", { value: true });
|
16 | var ts = require("typescript");
|
17 | var Lint = require("tslint");
|
18 | var tsutils = require("tsutils");
|
19 | var AstUtils_1 = require("./utils/AstUtils");
|
20 | var TypeGuard_1 = require("./utils/TypeGuard");
|
21 | var FAILURE_STATIC_FOUND = 'Static invocation of underscore function found. Prefer instance version instead: ';
|
22 | var FAILURE_INSTANCE_FOUND = 'Underscore instance wrapping of variable found. Prefer underscore static functions instead: ';
|
23 | var FUNCTION_NAMES = [
|
24 | 'each',
|
25 | 'forEach',
|
26 | 'map',
|
27 | 'collect',
|
28 | 'reduce',
|
29 | 'inject',
|
30 | 'foldl',
|
31 | 'reduceRight',
|
32 | 'foldr',
|
33 | 'find',
|
34 | 'detect',
|
35 | 'filter',
|
36 | 'select',
|
37 | 'where',
|
38 | 'findWhere',
|
39 | 'reject',
|
40 | 'every',
|
41 | 'all',
|
42 | 'some',
|
43 | 'any',
|
44 | 'contains',
|
45 | 'include',
|
46 | 'invoke',
|
47 | 'pluck',
|
48 | 'max',
|
49 | 'min',
|
50 | 'sortBy',
|
51 | 'groupBy',
|
52 | 'indexBy',
|
53 | 'countBy',
|
54 | 'shuffle',
|
55 | 'sample',
|
56 | 'toArray',
|
57 | 'size',
|
58 | 'partition',
|
59 | 'first',
|
60 | 'head',
|
61 | 'take',
|
62 | 'initial',
|
63 | 'last',
|
64 | 'rest',
|
65 | 'tail',
|
66 | 'drop',
|
67 | 'compact',
|
68 | 'flatten',
|
69 | 'without',
|
70 | 'union',
|
71 | 'intersection',
|
72 | 'difference',
|
73 | 'uniq',
|
74 | 'unique',
|
75 | 'object',
|
76 | 'zip',
|
77 | 'unzip',
|
78 | 'indexOf',
|
79 | 'findIndex',
|
80 | 'lastIndexOf',
|
81 | 'findLastIndex',
|
82 | 'sortedIndex',
|
83 | 'range'
|
84 | ];
|
85 | var Rule = (function (_super) {
|
86 | __extends(Rule, _super);
|
87 | function Rule() {
|
88 | return _super !== null && _super.apply(this, arguments) || this;
|
89 | }
|
90 | Rule.prototype.apply = function (sourceFile) {
|
91 | return this.applyWithFunction(sourceFile, walk, this.parseOptions(this.getOptions()));
|
92 | };
|
93 | Rule.prototype.parseOptions = function (options) {
|
94 | var parsed = {
|
95 | style: 'instance'
|
96 | };
|
97 | options.ruleArguments.forEach(function (opt) {
|
98 | if (TypeGuard_1.isObject(opt)) {
|
99 | if (opt.style === 'static') {
|
100 | parsed.style = 'static';
|
101 | }
|
102 | }
|
103 | });
|
104 | return parsed;
|
105 | };
|
106 | Rule.metadata = {
|
107 | ruleName: 'underscore-consistent-invocation',
|
108 | type: 'maintainability',
|
109 | description: 'Enforce a consistent usage of the _ functions',
|
110 | options: null,
|
111 | optionsDescription: '',
|
112 | typescriptOnly: true,
|
113 | issueClass: 'Non-SDL',
|
114 | issueType: 'Warning',
|
115 | severity: 'Low',
|
116 | level: 'Opportunity for Excellence',
|
117 | group: 'Clarity',
|
118 | commonWeaknessEnumeration: '398, 710'
|
119 | };
|
120 | return Rule;
|
121 | }(Lint.Rules.AbstractRule));
|
122 | exports.Rule = Rule;
|
123 | function walk(ctx) {
|
124 | function isStaticUnderscoreInstanceInvocation(node) {
|
125 | if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
|
126 | var propExpression = node.expression;
|
127 | if (propExpression.expression.kind === ts.SyntaxKind.CallExpression) {
|
128 | var call = propExpression.expression;
|
129 | var target = AstUtils_1.AstUtils.getFunctionTarget(call);
|
130 | var functionName = AstUtils_1.AstUtils.getFunctionName(call);
|
131 | if (target === undefined && functionName === '_' && call.arguments.length === 1) {
|
132 | var underscoreFunctionName = AstUtils_1.AstUtils.getFunctionName(node);
|
133 | return FUNCTION_NAMES.indexOf(underscoreFunctionName) > -1;
|
134 | }
|
135 | }
|
136 | }
|
137 | return false;
|
138 | }
|
139 | function isStaticUnderscoreInvocation(node) {
|
140 | var target = AstUtils_1.AstUtils.getFunctionTarget(node);
|
141 | if (target !== '_') {
|
142 | return false;
|
143 | }
|
144 | var functionName = AstUtils_1.AstUtils.getFunctionName(node);
|
145 | return FUNCTION_NAMES.indexOf(functionName) > -1;
|
146 | }
|
147 | function cb(node) {
|
148 | if (tsutils.isCallExpression(node)) {
|
149 | var functionName = AstUtils_1.AstUtils.getFunctionName(node);
|
150 | if (ctx.options.style === 'instance' && isStaticUnderscoreInvocation(node)) {
|
151 | ctx.addFailureAt(node.getStart(), node.getWidth(), FAILURE_STATIC_FOUND + '_.' + functionName);
|
152 | }
|
153 | if (ctx.options.style === 'static' && isStaticUnderscoreInstanceInvocation(node)) {
|
154 | ctx.addFailureAt(node.getStart(), node.getWidth(), FAILURE_INSTANCE_FOUND + node.expression.getText());
|
155 | }
|
156 | }
|
157 | return ts.forEachChild(node, cb);
|
158 | }
|
159 | return ts.forEachChild(ctx.sourceFile, cb);
|
160 | }
|
161 |
|
\ | No newline at end of file |