diff options
Diffstat (limited to 'node_modules/tslint/lib/rules/noUnboundMethodRule.js')
-rw-r--r-- | node_modules/tslint/lib/rules/noUnboundMethodRule.js | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/node_modules/tslint/lib/rules/noUnboundMethodRule.js b/node_modules/tslint/lib/rules/noUnboundMethodRule.js new file mode 100644 index 000000000..388cfa404 --- /dev/null +++ b/node_modules/tslint/lib/rules/noUnboundMethodRule.js @@ -0,0 +1,88 @@ +"use strict"; +/** + * @license + * Copyright 2017 Palantir Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var tslib_1 = require("tslib"); +var ts = require("typescript"); +var Lint = require("../index"); +var Rule = (function (_super) { + tslib_1.__extends(Rule, _super); + function Rule() { + return _super !== null && _super.apply(this, arguments) || this; + } + Rule.prototype.applyWithProgram = function (sourceFile, program) { + return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program)); + }; + return Rule; +}(Lint.Rules.TypedRule)); +/* tslint:disable:object-literal-sort-keys */ +Rule.metadata = { + ruleName: "no-unbound-method", + description: "Warns when a method is used as outside of a method call.", + optionsDescription: "Not configurable.", + options: null, + optionExamples: [true], + type: "functionality", + typescriptOnly: true, + requiresTypeInfo: true, +}; +/* tslint:enable:object-literal-sort-keys */ +Rule.FAILURE_STRING = "Avoid referencing unbound methods which may cause unintentional scoping of 'this'."; +exports.Rule = Rule; +var Walker = (function (_super) { + tslib_1.__extends(Walker, _super); + function Walker() { + return _super !== null && _super.apply(this, arguments) || this; + } + Walker.prototype.visitPropertyAccessExpression = function (node) { + if (!isSafeUse(node)) { + var symbol = this.getTypeChecker().getSymbolAtLocation(node); + var declaration = symbol === undefined ? undefined : symbol.valueDeclaration; + if (declaration !== undefined && isMethod(declaration)) { + this.addFailureAtNode(node, Rule.FAILURE_STRING); + } + } + _super.prototype.visitPropertyAccessExpression.call(this, node); + }; + return Walker; +}(Lint.ProgramAwareRuleWalker)); +function isMethod(node) { + switch (node.kind) { + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.MethodSignature: + return true; + default: + return false; + } +} +function isSafeUse(node) { + var parent = node.parent; + switch (parent.kind) { + case ts.SyntaxKind.CallExpression: + return parent.expression === node; + case ts.SyntaxKind.TaggedTemplateExpression: + return parent.tag === node; + // E.g. `obj.method.bind(obj)`. + case ts.SyntaxKind.PropertyAccessExpression: + return true; + // Allow most binary operators, but don't allow e.g. `myArray.forEach(obj.method || otherObj.otherMethod)`. + case ts.SyntaxKind.BinaryExpression: + return parent.operatorToken.kind !== ts.SyntaxKind.BarBarToken; + default: + return false; + } +} |