如果在循环内部使用,则强制将 getter 结果存储在变量中
Force to store getter result in variable if it is used inside of the loop
考虑关注 class
class Smth {
get functionWithSomeVeryUniqueName() {
// Some heavy calculations are here
return obj => obj; // Actually uses some vars from closure calculated above
}
}
我想在循环内访问 getter 时出现 tslint 错误。
我。 e.以下任何行都应被视为错误:
for (var x of a) smth.functionWithSomeVeryUniqueName(x);
a.forEach(x => smth.functionWithSomeVeryUniqueName(x))
a.map(x => smth.functionWithSomeVeryUniqueName(x))
for (var q=0; q<a.length; ++q) smth.functionWithSomeVeryUniqueName(x);
以及以下任何一项 - 好:
var functionWithSomeVeryUniqueName = smth.functionWithSomeVeryUniqueName;
for (var x of a) functionWithSomeVeryUniqueName(x);
a.forEach(x => functionWithSomeVeryUniqueName(x))
a.map(x => functionWithSomeVeryUniqueName(x))
for (var q=0; q<a.length; ++q) functionWithSomeVeryUniqueName(x);
这个也很好,因为参数只计算一次:
a.map(smth.functionWithSomeVeryUniqueName)
循环外的调用应该是有效的:
var x = smth.functionWithSomeVeryUniqueName(mySingleObject)
可以配置什么 tslint 规则来做这样的事情?
请注意,访问中的名称检查和点就足够了,我不需要确保函数属于某个具体的 class。
好像我制定了相应的规则(demo on AstExplorer):
import * as Lint from "tslint";
import * as ts from "typescript";
const arrayMethods = new Set(["find", "findIndex", "sort", "forEach", "filter", "flatMap", "map", "every", "some", "reduce", "reduceRight"]);
export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new DisallowGetterInsideOfTheLoopWalker(sourceFile, this.getOptions()));
}
}
class DisallowGetterInsideOfTheLoopWalker extends Lint.RuleWalker {
private loops = 0;
private names: Set<string>;
constructor(sourceFile, options) {
super(sourceFile, options);
this.loops = 0;
this.names = new Set(["functionWithSomeVeryUniqueName"] /* options.ruleArguments */);
}
public visitCallExpression(node: ts.CallExpression) {
var isLoop = node.expression.kind === ts.SyntaxKind.PropertyAccessExpression && arrayMethods.has(node.expression.name.text);
this.loops += isLoop as any;
super.visitPropertyAccessExpression(node);
this.loops -= isLoop as any;
}
public visitPropertyAccessExpression(node: ts.PropertyAccessExpression) {
if (this.loops && this.names.has(node.name.text) && (this.loops > 1 || node.parent.kind === ts.SyntaxKind.CallExpression && node.parent.expression === node)) {
this.addFailure(this.createFailure(node.name.pos, node.name.end - node.name.pos, `Do not get ${node.name.text} inside of the loop`));
}
super.visitPropertyAccessExpression(node);
}
public visitForOfStatement(node: ts.ForOfStatement) {
this.loops += 2;
super.visitForOfStatement(node);
this.loops -= 2;
}
public visitForInStatement(node: ts.ForInStatement) {
this.loops += 2;
super.visitForInStatement(node);
this.loops -= 2;
}
public visitForStatement(node: ts.ForStatement) {
this.loops += 2;
super.visitForStatement(node);
this.loops -= 2;
}
public visitDoStatement(node: ts.DoStatement) {
this.loops += 2;
super.visitDoStatement(node);
this.loops -= 2;
}
public visitWhileStatement(node: ts.WhileStatement) {
this.loops += 2;
super.visitWhileStatement(node);
this.loops -= 2;
}
}
无效案例:
for (var x of a) smth.functionWithSomeVeryUniqueName(x);
for (var x in obj) smth.functionWithSomeVeryUniqueName(x);
a.forEach(x => smth.functionWithSomeVeryUniqueName(x))
a.map(x => smth.functionWithSomeVeryUniqueName(x))
a.map(x => smth.functionWithSomeVeryUniqueName<T>(x))
for (var q=0; q<a.length; ++q) smth.functionWithSomeVeryUniqueName(x);
do smth.functionWithSomeVeryUniqueName(x); while (0)
while (1) smth.functionWithSomeVeryUniqueName(x);
while (1) (smth.functionWithSomeVeryUniqueName)(x);
while (1) var f = smth.functionWithSomeVeryUniqueName;
while (1) (smth as any).functionWithSomeVeryUniqueName;
有效案例:
var functionWithSomeVeryUniqueName = smth.functionWithSomeVeryUniqueName;
for (var x of a) functionWithSomeVeryUniqueName(x);
for (var x in obj) functionWithSomeVeryUniqueName(x);
a.forEach(x => functionWithSomeVeryUniqueName(x))
a.map(x => functionWithSomeVeryUniqueName(x))
for (var q=0; q<a.length; ++q) functionWithSomeVeryUniqueName(x);
do functionWithSomeVeryUniqueName(x); while (0)
while (1) functionWithSomeVeryUniqueName(x);
while (1) (functionWithSomeVeryUniqueName)(x);
a.map(smth.functionWithSomeVeryUniqueName)
smth.functionWithSomeVeryUniqueName(mySingleObject)
不需要的有效案例:
a.map(x => (smth.functionWithSomeVeryUniqueName)(x))
考虑关注 class
class Smth {
get functionWithSomeVeryUniqueName() {
// Some heavy calculations are here
return obj => obj; // Actually uses some vars from closure calculated above
}
}
我想在循环内访问 getter 时出现 tslint 错误。
我。 e.以下任何行都应被视为错误:
for (var x of a) smth.functionWithSomeVeryUniqueName(x);
a.forEach(x => smth.functionWithSomeVeryUniqueName(x))
a.map(x => smth.functionWithSomeVeryUniqueName(x))
for (var q=0; q<a.length; ++q) smth.functionWithSomeVeryUniqueName(x);
以及以下任何一项 - 好:
var functionWithSomeVeryUniqueName = smth.functionWithSomeVeryUniqueName;
for (var x of a) functionWithSomeVeryUniqueName(x);
a.forEach(x => functionWithSomeVeryUniqueName(x))
a.map(x => functionWithSomeVeryUniqueName(x))
for (var q=0; q<a.length; ++q) functionWithSomeVeryUniqueName(x);
这个也很好,因为参数只计算一次:
a.map(smth.functionWithSomeVeryUniqueName)
循环外的调用应该是有效的:
var x = smth.functionWithSomeVeryUniqueName(mySingleObject)
可以配置什么 tslint 规则来做这样的事情?
请注意,访问中的名称检查和点就足够了,我不需要确保函数属于某个具体的 class。
好像我制定了相应的规则(demo on AstExplorer):
import * as Lint from "tslint";
import * as ts from "typescript";
const arrayMethods = new Set(["find", "findIndex", "sort", "forEach", "filter", "flatMap", "map", "every", "some", "reduce", "reduceRight"]);
export class Rule extends Lint.Rules.AbstractRule {
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new DisallowGetterInsideOfTheLoopWalker(sourceFile, this.getOptions()));
}
}
class DisallowGetterInsideOfTheLoopWalker extends Lint.RuleWalker {
private loops = 0;
private names: Set<string>;
constructor(sourceFile, options) {
super(sourceFile, options);
this.loops = 0;
this.names = new Set(["functionWithSomeVeryUniqueName"] /* options.ruleArguments */);
}
public visitCallExpression(node: ts.CallExpression) {
var isLoop = node.expression.kind === ts.SyntaxKind.PropertyAccessExpression && arrayMethods.has(node.expression.name.text);
this.loops += isLoop as any;
super.visitPropertyAccessExpression(node);
this.loops -= isLoop as any;
}
public visitPropertyAccessExpression(node: ts.PropertyAccessExpression) {
if (this.loops && this.names.has(node.name.text) && (this.loops > 1 || node.parent.kind === ts.SyntaxKind.CallExpression && node.parent.expression === node)) {
this.addFailure(this.createFailure(node.name.pos, node.name.end - node.name.pos, `Do not get ${node.name.text} inside of the loop`));
}
super.visitPropertyAccessExpression(node);
}
public visitForOfStatement(node: ts.ForOfStatement) {
this.loops += 2;
super.visitForOfStatement(node);
this.loops -= 2;
}
public visitForInStatement(node: ts.ForInStatement) {
this.loops += 2;
super.visitForInStatement(node);
this.loops -= 2;
}
public visitForStatement(node: ts.ForStatement) {
this.loops += 2;
super.visitForStatement(node);
this.loops -= 2;
}
public visitDoStatement(node: ts.DoStatement) {
this.loops += 2;
super.visitDoStatement(node);
this.loops -= 2;
}
public visitWhileStatement(node: ts.WhileStatement) {
this.loops += 2;
super.visitWhileStatement(node);
this.loops -= 2;
}
}
无效案例:
for (var x of a) smth.functionWithSomeVeryUniqueName(x);
for (var x in obj) smth.functionWithSomeVeryUniqueName(x);
a.forEach(x => smth.functionWithSomeVeryUniqueName(x))
a.map(x => smth.functionWithSomeVeryUniqueName(x))
a.map(x => smth.functionWithSomeVeryUniqueName<T>(x))
for (var q=0; q<a.length; ++q) smth.functionWithSomeVeryUniqueName(x);
do smth.functionWithSomeVeryUniqueName(x); while (0)
while (1) smth.functionWithSomeVeryUniqueName(x);
while (1) (smth.functionWithSomeVeryUniqueName)(x);
while (1) var f = smth.functionWithSomeVeryUniqueName;
while (1) (smth as any).functionWithSomeVeryUniqueName;
有效案例:
var functionWithSomeVeryUniqueName = smth.functionWithSomeVeryUniqueName;
for (var x of a) functionWithSomeVeryUniqueName(x);
for (var x in obj) functionWithSomeVeryUniqueName(x);
a.forEach(x => functionWithSomeVeryUniqueName(x))
a.map(x => functionWithSomeVeryUniqueName(x))
for (var q=0; q<a.length; ++q) functionWithSomeVeryUniqueName(x);
do functionWithSomeVeryUniqueName(x); while (0)
while (1) functionWithSomeVeryUniqueName(x);
while (1) (functionWithSomeVeryUniqueName)(x);
a.map(smth.functionWithSomeVeryUniqueName)
smth.functionWithSomeVeryUniqueName(mySingleObject)
不需要的有效案例:
a.map(x => (smth.functionWithSomeVeryUniqueName)(x))