用来自于注释内容的子树替换 JavaScript AST 中的注释。

13
我是doctest,一个用于JavaScript和CoffeeScript的快速而简单的doctests工具的作者。我想通过使用JavaScript解析器而不是正则表达式来定位注释,使该库更加简洁。
我想使用EsprimaAcorn来完成以下任务:
  1. 创建AST
  2. 遍历树,并对于每个注释节点:
    1. 从注释节点的文本中创建AST
    2. 使用这个子树替换主树中的注释节点
输入:
!function() {

  // > toUsername("Jesper Nøhr")
  // "jespernhr"
  var toUsername = function(text) {
    return ('' + text).replace(/\W/g, '').toLowerCase()
  }

}()

输出:

!function() {

  doctest.input(function() {
    return toUsername("Jesper Nøhr")
  });
  doctest.output(4, function() {
    return "jespernhr"
  });
  var toUsername = function(text) {
    return ('' + text).replace(/\W/g, '').toLowerCase()
  }

}()

我不知道怎么做。Acorn提供了一个walker,它需要一个节点类型和一个函数,并遍历树,在遇到指定类型的节点时调用该函数。这看起来很有希望,但不适用于注释。
使用Esprima,我可以使用esprima.parse(input, {comment: true, loc: true}).comments获取注释,但我不确定如何更新树。

1
你尝试过JSShaper吗? - Artem Sobolev
我不知道那个项目。看起来很有前途。 - davidchambers
2个回答

3
大多数生成AST的解析器都会忽略注释。我不知道Esprima或Acorn会怎么处理,但这可能是问题所在。
实际上,Esprima将注释捕获列为当前错误: http://code.google.com/p/esprima/issues/detail?id=197 ...... Acorn的代码就在GitHub上。它似乎也会忽略注释。
因此,看起来你需要修复其中一个解析器以先捕获注释,此后你的任务应该很简单,否则你就无法进行。

我们的DMS软件重建工具包具有JavaScript解析器,可以捕获树中的注释。它还具有语言子字符串解析器,可用于将注释文本解析为JavaScript AST(例如函数声明、表达式、变量声明等)并支持将这些新AST嫁接到主树中的机制。如果您要操作AST,则此子字符串功能很可能很重要:大多数解析器不会解析任意语言片段,它们仅被连接以解析“整个程序”。对于DMS,没有要替换的注释节点;有与AST节点相关联的注释,因此嫁接过程比“替换注释节点”要棘手一些。但仍然相当容易。

我观察到大多数解析器(包括这些)通过使用或应用正则表达式等价物来读取源代码并将其分解为标记。因此,如果您已经使用它们来定位注释(这意味着还要使用它们来定位*非*注释以丢弃,例如,您需要识别包含类似注释的文本的字符串文字并忽略它们),那么在找到注释方面,您已经做得和解析器一样好了。如果您只想精确地用其内容替换它们,并去除带有注释前缀/后缀/* */的源流,这似乎恰好可以实现您想要的功能,因此所有这些解析机制似乎都是过度设计。

2
您已经可以使用Esprima来实现您想要的功能:
  1. 解析代码,获取注释(作为数组)。
  2. 遍历注释,查看每个注释是否是您感兴趣的内容。
  3. 如果需要转换注释,请注意其范围。收集所有转换。
  4. 将变换应用回到第一步,以便范围不会移动。
技巧在于不改变AST。只需像直接在源字符串上执行典型的搜索替换一样应用文本更改即可。由于替换的位置可能会移动,因此您需要收集所有内容,然后从最后一个开始执行。有关如何执行此类转换的示例,请参阅我的博客文章"从双引号到单引号"(它处理字符串引号,但原则仍然相同)。
最后但并非最不重要的是,您可能希望使用稍微高级一些的实用程序,例如Rocambole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接