Giter Club home page Giter Club logo

hello-ast-types's Introduction

Learning ast-types

The examples here are based in the examples in https://github.com/benjamn/ast-types README.md

index.js

➜  hello-ast-types git:(master) node introduction/index.js

The AST built for

if (foo) {
    foo();
}

is:

{
  "test": {
    "name": "foo",
    "loc": null,
    "type": "Identifier",
    "comments": null,
    "optional": false,
    "typeAnnotation": null
  },
  "consequent": {
    "body": [
      {
        "expression": {
          "callee": {
            "name": "foo",
            "loc": null,
            "type": "Identifier",
            "comments": null,
            "optional": false,
            "typeAnnotation": null
          },
          "arguments": [],
          "loc": null,
          "type": "CallExpression",
          "comments": null,
          "optional": false,
          "typeArguments": null
        },
        "loc": null,
        "type": "ExpressionStatement",
        "comments": null
      }
    ],
    "loc": null,
    "type": "BlockStatement",
    "comments": null,
    "directives": []
  },
  "alternate": null,
  "loc": null,
  "type": "IfStatement",
  "comments": null
}

visitmemberexpression.js

The 5th edition of ECMAScript (ES5) forbids the use of arguments.callee.

The goal of this code example: you want to detect uses of this old trick to update the code.

Here is an execution of the example:

  hello-ast-types git:(flow-parser)  node visitmemberexpression.js 
Input:

/* Early versions of JavaScript did not allow named function expressions, 
and for this reason you could not make a recursive function expression. 
May be you want to detect uses of this old trick to update the code.
*/

var fac = function(n) { return !(n > 1) ? 1 : arguments.callee(n - 1) * n; }

---
Warning! 'arguments.callee' is used in this code

The summarized AST for the input code

var fac = function(n) { return !(n > 1) ? 1 : arguments.callee(n - 1) * n; }

is:

 compast -p 'var fac = function(n) { return !(n > 1) ? 1 : arguments.callee(n - 1) * n; }'
['Program',
  [ 'VariableDeclaration',
    [ 'VariableDeclarator',
      [ 'Identifier', 'fac' ],
      [ 'FunctionExpression',
        [ 'Identifier', 'n' ],
        [ 'BlockStatement',
          [ 'ReturnStatement',
            [ 'ConditionalExpression',
              [ 'UnaryExpression', '!',
                [ 'BinaryExpression', '>',  [ 'Identifier', 'n' ], [ 'Literal', 1 ] ]
              ],
              [ 'Literal', 1 ],
              [ 'BinaryExpression', 
                '*',
                [ 'CallExpression',
                  [ 'MemberExpression',
                    [ 'Identifier', 'arguments' ],  [ 'Identifier', 'callee' ]
                  ],
                  [ 'BinaryExpression', '-', [ 'Identifier', 'n' ], [ 'Literal', 1 ] ]
                ],
                [ 'Identifier', 'n' ]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
]

In the following code n is an abbreviation for the namedTypes object provided by ast-types:

import { visit, namedTypes as n, } from "ast-types";

Remmber that:

  1. The object n has a check method to check the type of a node.
  2. The children of a MemberExpression node have names object and property:
> e = require('espree')
> e.VisitorKeys.MemberExpression
[ 'object', 'property' ]
> b = require("ast-types").builder
> gfn = require("ast-types").getFieldNames, null
> gfn({type: "MemberExpression"})
[ 'type', 'optional', 'object', 'property', 'computed' ]

Notice how

  1. We traverse the AST visiting the MemberExpression nodes
  2. We check that the child object of the MemberExpression node is of type Identifier and its name is arguments
  3. We check that the child property of the MemberExpression node is of type Identifier and its name is callee
visit(ast, {
  visitMemberExpression(path) {
    var node = path.node;
    if (
      n.Identifier.check(node.object) && 
      node.object.name === "arguments" &&
      n.Identifier.check(node.property)
    ) {
      if (node.property.name == "callee") console.error("Warning! 'arguments.callee' is used in this code");
    }
    this.traverse(path);
  }
});

See the solution in file visit/visitmemberexpression.js

spread-operator.js

Translate ES6 spread operator to older versions of JS.

Transforming ...rest parameters into browser-runnable ES5 JavaScript:

For the input:

let code = `
function tutu(x, ...rest) {
    return x + rest[0];
}
module.exports = tutu;
`;

gives the output:

visit git:(master)  node spread-operator.js > salida.cjsvisit git:(master)  cat salida.cjs 
function tutu(x) {
    var rest = Array.prototype.slice.call(arguments, 1);
    return x + rest[0];
}

module.exports = tutu;

That we can use this way:

visit git:(master)  node
> tutu = require("./salida.cjs")
[Function: tutu]
> tutu(2,3,4,5)
5

See the full code at visit/spread-operator.js

check-this-usage.js

Implement a function that determines if a given function node refers to this

This example has been modified regarding not only the usage of super but also due to the fact that visitFunction is triggered by the outer function and the original produced an erroneous result

➜  hello-ast-types git:(master) ✗ npm run this

> [email protected] this
> node check-this-usage.js


function tutu() {
    return this.prop+4;
}

Inside Function visitor tutu
inside thisexpression
true
----

function tutu() {
    return prop+4;
}

Inside Function visitor tutu
false
----

function tutu() {
    function titi() {
        return this.prop+4;
    }
    
    return prop+4;
}

Inside Function visitor tutu
Inside Function visitor titi
false
----

  function tutu() {
    return super();
  }

Inside Function visitor tutu
true
----

  function tutu() {
    return super.meth();
  }

Inside Function visitor tutu
true
----

hello-ast-types's People

Contributors

crguezl avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.