typescript 的抽象语法树

1,369 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

前言

近期在进行一项需求需要追踪项目各文件所使用的依赖,通过现有项目的特征,需要对项目每个 ts 文件进行解析,然后再获取其每个部分,所以需要先解析 ts文件,得到一个 抽象语法树。

抽象语法树(AST)

源代码语法结构的一种抽象表示。主要以树状表示,树上每个节点都是源代码中的一种结构。我们常用的浏览器就是通过将 javaScript 的代码转为抽象语法树,再进行分析等操作。所以抽象语法树是便于程序的分析

- FunctionDeclaration:
  - id:
    - Identifier:
      - name: square
  - params [1]
    - Identifier
      - name: n
  - body:
    - BlockStatement
      - body [1]
        - ReturnStatement
          - argument
            - BinaryExpression
              - operator: *
              - left
                - Identifier
                  - name: n
              - right
                - Identifier
                  - name: n

推荐一个在线 AST 转换网站:astexplorer.net/

AST 使用场景:

  • Eslint 进行代码规范检查
  • 通过 babel 将译 javascript 语法
  • 编辑器的错误提示、代码格式化,代码补全,代码高亮

查阅资料,对于 typescript 其提供了相关的语法解析

var ts = require('typescript');

为了解决我的需求,必须先遍历文件,然后读取文件内的内容,可以使用 fs.readFile 这样就可以读取到 ts 文件的源代码。

对 typescript 的解析,使用 createSourceFile 解析

 const astResult = ts.createSourceFile(fileName, data, ts.ScriptTarget.ES5, /*setParentNodes*/ true);

astResult 就是 ts 文件的解析后的抽象语法树,接下来要处理的就是对于遍历树的节点。

class User {
  //.....
}

ts 文件都有 class 类型,所以需先进行树节点类型判断是否是 class 类型,如果是的话则继续 class 内属性的节点的查找

 if (node.kind === SyntaxKind.ClassDeclaration) {
 // 如果是声明为 class 类型,可继续对当前树节点的字节点进行遍历
   //;.....
 }
​
 if (node.kind === SyntaxKind.Constructor) {
   
 }

SyntaxKind 是个枚举类型,有很多个枚举值,具体可点击查看

整个过程就很轻松从抽象语法树上得到想要的内容,然后进行一些相关的操作。