【问题标题】:Distinguish methods and properties区分方法和属性
【发布时间】:2016-06-12 16:54:21
【问题描述】:

问题:

我目前正在改进 eslint-plugin-jasmine 包的 valid-expect rule 以尝试在未调用匹配器时处理另一个无效的 Jasmine expect() 用法:

expect(true).toBeDefined;

有效用法:

expect(true).toBeDefined();

我已经很接近了 - 我可以确定 expect() 上有一个成员表达式:

// matcher was not called
MemberExpression: function (node) {
  if (node.object && node.object.callee.name === 'expect') {
    console.log(node.property)
  }
}

node.property 在有效和无效情况下都是Identifier 类型:

Node {
  type: 'Identifier',
  start: 13,
  end: 24,
  loc: 
   SourceLocation {
     start: Position { line: 1, column: 13 },
     end: Position { line: 1, column: 24 } },
  range: [ 13, 24 ],
  name: 'toBeDefined' }

并且没有任何明显的迹象表明这是一个属性或方法。

问题:

如何确定 ESLint 中的属性是否可调用?

【问题讨论】:

    标签: javascript testing jasmine eslint static-code-analysis


    【解决方案1】:

    expect(true).toBeDefined 被解析为MemberExpression 节点,但expect(true).toBeDefined() 被解析为CallExpression。我不是真的 100% 确定为什么会发生这种情况,但在第二种情况下,似乎认为直到开括号的整个语句都是一个 CallExpression,我希望有两个单独的 CallExpression,但似乎并非如此。

    所以你可以做的是收听CallExpression 并检查被调用者是Identifier,名称为expect。然后检查它的祖父母是MemberExpression还是另一个CallExpression

    【讨论】:

    • 很有趣,感谢您对此进行调查!我实际上必须去父母的父母那里检查类型。如果这是一个方法调用,node.parent.parent.type 将是CallExpression,如果是一个属性,则为ExpressionStatement。这是你的意思吗?请注意,node.parent.type 在这两种情况下仍然是 MemberExpression..(gist.github.com/alecxe/…)
    • 是的,你必须去祖父节点。对此感到抱歉。
    • 好吧,这行得通,包含测试并发送 PR。谢谢。