onvno / pokerface

日常技术文章阅读整理
3 stars 0 forks source link

20200429 - AST #92

Open onvno opened 4 years ago

onvno commented 4 years ago

项目中需要做一次校验处理,要对JSON做些小动作,开始了对AST的了解。 类似的需求如这个问题:fs 如何读取 js 模块的注释,从论坛回复得到了一些不错的启发。

可以试试用 jsdoc 或 jscodeshift 的 API jscodeshift 是 FB 家的,它是对 recast 的 wrapper,而 recast 是 esprima 的 wrapper

  1. AST in JS:好文无人问津,介绍了常用的AST包以及babel的一些实现。同时还有一个在线AST工具
  2. AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解:虽然标题很唬人,不过还是介绍到了recast这个利器。

在简单测试,发现recast对单行注释可以拿到,反倒是esprima这里会有问题

onvno commented 4 years ago

jscodeshift相关

使用介绍

onvno commented 4 years ago

jscodeshift issue

How to transform comments in a line

const comment = builders.Line(" Not for translation");
comment.trailing = true;
varDecl.comments = node.comments || [];
varDecl.comments.push(comment);

or

// Put a /* block comment */ immediately after the string literal:
const comment = builders.Block(" Not for translation ");
comment.trailing = true;
stringLiteral.comments = stringLiteral.comments || [];
stringLiteral.comments.push(comment);
onvno commented 4 years ago

jscodeshift一些示例

如何添加comment: https://astexplorer.net/#/nmno5f20v6

如何修改comment: https://astexplorer.net/#/gist/8c7d9f81226bbbdee5d9c7a2468ddaa0/c3d93b44e2bf90e0ff2553ec1c8d85dd2daf807e

onvno commented 4 years ago

如何学习jscodeshift,在issue212热心小哥答疑解惑,还提到如何学习使用这个库:

As far as I know there aren't any great docs. 😕

Some stuff I've done to learn:

I initially got started by reading this tutorial: https://www.toptal.com/javascript/write-code-to-rewrite-your-code AST Explorer is nice for understanding the AST format. You can dig into the AST on the right and see what's there. You might have been able to dig through and find comments there, for example. You can also console.log anything and look at the value and prototype in the Chrome console to get a better sense of what you can do with any particular thing (and autocomplete is helpful). I have the jscodeshift and recast repos on my machine and sometimes dig through them to figure out what functions are there and what I have access to. There are also plenty of examples out there to look at, e.g. https://github.com/facebook/jscodeshift#example-codemods

onvno commented 4 years ago

replace替换,使用了这个简单粗暴的方法

module.exports = function(file, api, options) {
    const j = api.jscodeshift;
    const root = j(file.source);

    j(root.find(j.ObjectExpression).at(0).get())
        .replaceWith(JSON.stringify({foo: 4, bar: '5'}));

        return root.toSource();
}

原始:

// Some code ...

const someObj = {
  x: {
    foo: 3
  }
};

// Some code ...

转换后结果

// Some code ...

const someObj = {"foo":4,"bar":"5"};

// Some code ...
onvno commented 4 years ago

一些文章收集:

onvno commented 4 years ago

通过j(p)包裹返回的路径,所包含的属性可查看此链接:https://github.com/benjamn/ast-types#nodepath 一些方法可以用到:

// Replace one node with another node:
var fifth = path.get("elements", 4);
fifth.replace(newNode);

// Now do some stuff that might rearrange the list, and this replacement
// remains safe:
fifth.replace(newerNode);

// Replace the third element in an array with two new nodes:
path.get("elements", 2).replace(
  b.identifier("foo"),
  b.thisExpression()
);

// Remove a node and its parent if it would leave a redundant AST node:
//e.g. var t = 1, y =2; removing the `t` and `y` declarators results in `var undefined`.
path.prune(); //returns the closest parent `NodePath`.

// Remove a node from a list of nodes:
path.get("elements", 3).replace();

// Add three new nodes to the beginning of a list of nodes:
path.get("elements").unshift(a, b, c);

// Remove and return the first node in a list of nodes:
path.get("elements").shift();

// Push two new nodes onto the end of a list of nodes:
path.get("elements").push(d, e);

// Remove and return the last node in a list of nodes:
path.get("elements").pop();

// Insert a new node before/after the seventh node in a list of nodes:
var seventh = path.get("elements", 6);
seventh.insertBefore(newNode);
seventh.insertAfter(newNode);

// Insert a new element at index 5 in a list of nodes:
path.get("elements").insertAt(5, newNode);
onvno commented 4 years ago

json5-writer:想知道如何完整写如AST,可以参考此源码,同时为了快捷支持json5,做了一个四两拨千斤的处理x={}

onvno commented 4 years ago

json5源码思路 依次读取json,根据语义上的分割截取,截取到的串进行存储。 存储后清空临时变量。 在过程中,会反复根据当前片段状态,更改下阶段的属性。