UNPKG

ts-simple-ast

Version:

TypeScript compiler wrapper for AST navigation and code generation.

181 lines (141 loc) 13.2 kB
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>ts-simple-ast - Manipulating the AST</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous"> <link rel="stylesheet" href="/assets/css/style.css?v=502728dc7b09041e36b06c50f79a13adbfb6f1b2"> <!-- <link rel="stylesheet" href="/assets/css/style.css?v=502728dc7b09041e36b06c50f79a13adbfb6f1b2"> <link rel="stylesheet" href="/assets/css/custom-style.css?v=502728dc7b09041e36b06c50f79a13adbfb6f1b2"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script src="/assets/js/main.js"></script>--> </head> <body> <div class="main"> <header class="container"> <div class="row"> <h1 onclick="document.location.href = '/'" class="headerLink">ts-simple-ast</h1> <!--<p class="subText">Simple way to navigate and manipulate the TypeScript AST.</p>--> </div> </header> <div class="container"> <div class="row"> <div class="col-md-3"> <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <nav class="sidebar-nav" id="navbarSupportedContent"> <ul class="navbar-nav navbar-default"> <li class="nav-item"> <a class="nav-link" href="/">Overview</a> </li> <li class="nav-item"> <a class="nav-link" href="/setup">Setup</a> </li> <li class="nav-item"> <a class="nav-link" href="/navigation">Navigation</a> </li> <li class="nav-item active"> <a class="nav-link" href="/manipulation">Manipulation</a> <ul> <li class=""><a href="/manipulation/settings">Settings</a></li> <li class=""><a href="/manipulation/renaming">Renaming</a></li> <li class=""><a href="/manipulation/removing">Removing</a></li> <li class=""><a href="/manipulation/order">Order</a></li> <li class=""><a href="/manipulation/code-writer">Code Writer</a></li> <li class=""><a href="/manipulation/performance">Performance</a></li> </ul> </li> <li class="nav-item"> <a class="nav-link" href="/emitting">Emitting</a> </li> <li class=""> <a class="nav-link" href="/details/index">Details</a> </li> <li class="nav-item"> <a class="nav-link" href="/utilities">Utilities</a> </li> <li class="nav-item"> <a class="nav-link" href="http://github.com/dsherret/ts-simple-ast">View on GitHub</a> </li> </ul> </nav> </div> <section class="container-fluid col-md-9"> <h2 id="manipulating-the-ast">Manipulating the AST</h2> <p>Most information about manipulation can be found in the <a href="../details">Details</a> section. This section only contains general information about manipulation.</p> <h3 id="replacing-any-node-with-new-text">Replacing any node with new text</h3> <p>This can be achieved with the <code class="highlighter-rouge">.replaceWithText(...)</code> method that exists on any node.</p> <h4 id="example">Example</h4> <p>Given the following code:</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">myVariable</span> <span class="o">=</span> <span class="nx">Some</span><span class="p">.</span><span class="nx">Property</span><span class="p">.</span><span class="nx">Access</span><span class="p">.</span><span class="nx">Expression</span><span class="p">;</span> </code></pre> </div> <p>You can replace the property access expression with new text by doing the following:</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">originalInitializer</span> <span class="o">=</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">getVariableDeclarations</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="nx">getInitializerOrThrow</span><span class="p">();</span> <span class="kd">const</span> <span class="nx">newInitializer</span> <span class="o">=</span> <span class="nx">originalInitializer</span><span class="p">.</span><span class="nx">replaceWithText</span><span class="p">(</span><span class="s2">"MyReference"</span><span class="p">);</span> </code></pre> </div> <p>That will make the source file hold the following text:</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">myVariable</span> <span class="o">=</span> <span class="nx">MyReference</span><span class="p">;</span> </code></pre> </div> <p>Note that <code class="highlighter-rouge">originalInitializer</code> will be forgotten after calling <code class="highlighter-rouge">.replaceWithText(...)</code> on it—an error will be thrown if you try to use it. You will have to use the new node returned by that method.</p> <h3 id="adding-inserting-and-removing-statements">Adding, inserting, and removing statements</h3> <p>Statements can be added, inserted, or removed from nodes with a body (ex. functions, methods, namespaces, source files).</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="c1">// add statements</span> <span class="kd">const</span> <span class="nx">statements</span> <span class="o">=</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">addStatements</span><span class="p">(</span><span class="s2">"console.log(5);\nconsole.log(6);"</span><span class="p">);</span> <span class="c1">// insert statements (index is the child index to insert at)</span> <span class="kd">const</span> <span class="nx">statements</span> <span class="o">=</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">insertStatements</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s2">"console.log(5);\nconsole.log(6);"</span><span class="p">);</span> <span class="c1">// remove statements</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">removeStatements</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">]);</span> <span class="c1">// removes statements from index 1 to 3</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">removeStatement</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// removes statement at index 1</span> </code></pre> </div> <p>When adding or inserting, you can also write using a <a href="code-writer">code writer</a>:</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="nx">functionDeclaration</span><span class="p">.</span><span class="nx">addStatements</span><span class="p">(</span><span class="nx">writer</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">writer</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s2">"if (true)"</span><span class="p">).</span><span class="nx">block</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">writer</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s2">"something;"</span><span class="p">);</span> <span class="p">});</span> <span class="p">});</span> </code></pre> </div> <h3 id="inserting-replacing-and-removing-any-text">Inserting, replacing, and removing any text</h3> <p>In some scenarios, a simple to use API might not have been implemented. If you find that’s the case, open an issue on GitHub.</p> <p>In the meantime, you can insert, replace, and remove text using the following methods, but <em>generally you will want to avoid using these if possible</em>:</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="c1">// insert text</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">insertText</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s2">"// some comment\n"</span><span class="p">);</span> <span class="c1">// replace text</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">replaceText</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">],</span> <span class="s2">"a"</span><span class="p">);</span> <span class="c1">// "// a comment\n"</span> <span class="c1">// remove text</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">removeText</span><span class="p">([</span><span class="nx">sourceFile</span><span class="p">.</span><span class="nx">getPos</span><span class="p">(),</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">getEnd</span><span class="p">()]);</span> </code></pre> </div> <p>These methods are also available on any node that has a body (functions, classes, enums, etc.)</p> <h4 id="warning"><strong>Warning</strong></h4> <p>If you use <code class="highlighter-rouge">insertText</code>, <code class="highlighter-rouge">replaceText</code>, or <code class="highlighter-rouge">removeText</code>, all previously navigated descendants of the node will be forgotten and not be available for use—an error will be thrown if you try to use them. You will have to renavigate to those nodes.</p> <p>For example:</p> <div class="language-typescript highlighter-rouge"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">classDeclaration</span> <span class="o">=</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">addClass</span><span class="p">({</span> <span class="na">name</span><span class="p">:</span> <span class="s2">"MyClass"</span> <span class="p">});</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">insertText</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s2">"// some comment\n"</span><span class="p">);</span> <span class="c1">// this will throw...</span> <span class="nx">classDeclaration</span><span class="p">.</span><span class="nx">getInstanceProperties</span><span class="p">();</span> <span class="c1">// you'll need to get the reference again:</span> <span class="nx">classDeclaration</span> <span class="o">=</span> <span class="nx">sourceFile</span><span class="p">.</span><span class="nx">getClass</span><span class="p">(</span><span class="s2">"MyClass"</span><span class="p">)</span><span class="o">!</span><span class="p">;</span> </code></pre> </div> </section> </div> </div> <footer> </footer> </div> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script> <!--[if !IE]><script>fixScale(document);</script><![endif]--> </body> </html>