如果在循环内使用,则强制将getter结果存储在变量中 [英] Force to store getter result in variable if it is used inside of the loop

查看:236
本文介绍了如果在循环内使用,则强制将getter结果存储在变量中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下类

class Smth {
  get functionWithSomeVeryUniqueName() {
    // Some heavy calculations are here
    return obj => obj; // Actually uses some vars from closure calculated above
  }
}

I希望对循环内的getter进行任何访问时都出现tslint错误。

I want to have a tslint error on any access to getter inside of the loop.

I。 e。以下任何行均应视为错误:

I. e. any of following lines should be considered bad:

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);

以及以下任意一项-好:

and any of the following - good:

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);

这也是一个好方法,因为参数仅计算一次:

And this one is good too as the argument is calculated only once:

a.map(smth.functionWithSomeVeryUniqueName)

并且循环的调用ouside应该是有效的:

And call ouside of the loop should be valid:

var x = smth.functionWithSomeVeryUniqueName(mySingleObject)

可以配置哪些tslint规则来执行此操作?

请注意,访问权限中的名称检查和点就足够了,我不需要确保该函数属于某个具体类。

Note that name check and dot in access are enough, I don' need to ensure that function belongs to some concrete class.

推荐答案

似乎我已经制定了相应的规则( / a>):

Seems like I've made corresponding rule (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))

这篇关于如果在循环内使用,则强制将getter结果存储在变量中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆