JS: rename variables for refactor (using an AST, not text)
Asked Answered
I

3

4

I often need to rename variables when refactoring code, which I currently do in a somewhat hacky way using regexs - I end up having to come with silly text workaround workarounds for the lack of actual structure, eg, rename 'req' to 'request' and avoid side effects with similar names like 'require'.

Thinking about this stuff: it's kind of like modifying the DOM with regexs: it just doesn't work.

I've learnt about ASTs and code structure modification tools like Esprima. Is there a tool to rename variables, Esprima based or otherwise?

Instantaneous answered 31/10, 2013 at 15:24 Comment(5)
Huh? What IDE are you using? Most allow you to rename variables just fine. shift+F6 in PHPStorm (and probably most other IDEs)Sophocles
@FritsvanCampen Using Sublime... by it default it emphasis 'use ⌘D to rename variables' which is just text based.Instantaneous
A non-programmer colleague of mine uses that one. I don't think it does any kind of code analysis. You need an IDE that understands your target programming language of course.Sophocles
@FritsvanCampen Yep, either an IDE with an AST based tool built in or a separate command line AST tool would do nicely.Instantaneous
Related: #17213139Abode
I
4

1. grasp.js

It looks like http://graspjs.com/ does exactly this.

grasp selector --replace replacement file.js

For example, to rename 'el' to 'element':

grasp '#el' --replace 'element' index.js

Official grasp.replace docs.

2. vscode

Visual Studio Code also includes a real replacement tool. Just right click a token and choose rename symbol.

enter image description here

Instantaneous answered 14/1, 2014 at 10:27 Comment(0)
W
2

I know you've been asking for 'a tool'; but I think it's better to use just esprima itself and the various general purpose tools on top of esprima, and roll your own renamer. Because it's really really easy, and then you have more control. Here is a complete example in just 12 lines of code. It uses escodegen and estraverse, both on github, and, as far as I can see kind of 'the standard' to use in conjunction with esprima. While esprima essentially gives the parse function string -> abstract syntax tree, escodegen essentially gives the reverse of that, i.e. abstract syntax tree -> string. And estraverse 'walks the tree' with the traverse method, thus helping to analyze or modify it.

Here the code:

function rename(code, renamingObj){
    var ast = esprima.parse(code);
    function callback(node){
        if (node.type==='Identifier') {
            if (node.name in renamingObj){
                node.name = renamingObj[node.name];
            }
        }
    }
    estraverse.traverse(ast, { enter: callback });
    return escodegen.generate(ast);
}

Testcase:

function blah(x,y){
    var difference = x + y;
    var product    = x - y;
    var sum        = x * y;
    return 42;
}
var renamingObj = {
    sum        : 'product',
    difference : 'sum',
    product    : 'difference'
};

run it:

rename(blah.toString(), renamingObj)

output:

function blah(x, y) {
    var sum = x + y;
    var difference = x - y;
    var product = x * y;
    return 42;
}

I would say, if you have something special to do, it's easier to modify above code than sifting through some tool documentation.

Weakly answered 7/11, 2019 at 13:58 Comment(0)
S
0

Our JavaScript Formatter/Obfuscator will do this reliably. It parses JavaScript, builds an AST, and either prints a pretty version, or an ugly (obfuscated) version. [The reason these are together is because pretty and ugly are opposite sides of the same coin!).

One of the things it does is scramble (whole) identifier names. By using the AST, it only renames "whole identifiers"; it won't confuse "req" with "require", or modify string or comment content by accident.

You can tell it to build a map of all identifier names, and then rename them all to themselves; change just one, and you get your rename effect. The identifier map looks like this:

    x ->  y
    p -> q
    ...

directing that x gets renamed to y, p to q, etc. You want:

    x -> x
    p -> q
    ...

to change just p to q. Its pretty easy to produce the identity map as your starting place.

I wouldn't say this is convenient, but it does work. It obviously doesn't know anything about scopes. (someday!).

See my bio for details. Many SO moderators hate tool questions, and they especially seem to dislike it when I provide a tool answer that includes a link to the tool. So you'll have to track down the link yourself, sorry. (Complain on Meta if you think this is dumb).

Sounder answered 31/10, 2013 at 16:20 Comment(5)
Ira, I have no problem with answers which detail how to use the tools made by your company to solve a specific problem. My problem with your answers from the start has been that you often do not clearly state that it is your company. Simply adding the word "our" is not sufficient, in my opinion. That little word can easily be missed. As far as I'm concerned, feel free to leave the link to the tool (or better, to an example of using the tool to solve a problem like this). Just please do clearly state, "my company makes this tool".Agalloch
I understand that you aren't happy with "our". We went around this issue over and over at Meta, and AFAICT, "our" was deemed to be adequate as an SO policy. There are other SO people that detest my answers no matter how labelled, detest tool answers as a general policy, etc, including apparantly a few (not all) of the moderators. If I operated at the intersection of everybody's opinion, I can't do anything, neither at SO or in the real world.Sounder
... (I should add) and some particularly detest my providing links in answers.Sounder
Ira, it's likely link-only answers that they don't like. BTW, I "checked up on you", and found myself upvoting many of your answers - the ones that said more than "our".Agalloch
My experience is they don't like the links, period. I don't generally say, "check this link, bye". Thanks for your upvotes; that may help me write more than "our" :-}Sounder

© 2022 - 2024 — McMap. All rights reserved.