<html>
<head>
<style><!--
  body {background-color:#ffffff;}
  .file {border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;}
  .pathname {font-family:monospace; float:right;}
  .fileheader {margin-bottom:.5em;}
  .diff {margin:0;}
  .tasklist {padding:4px;border:1px dashed #000000;margin-top:1em;}
  .tasklist ul {margin-top:0;margin-bottom:0;}
  tr.alt {background-color:#eeeeee}
  #added {background-color:#ddffdd;}
  #addedchars {background-color:#99ff99;font-weight:bolder;}
  tr.alt #added {background-color:#ccf7cc;}
  #removed {background-color:#ffdddd;}
  #removedchars {background-color:#ff9999;font-weight:bolder;}
  tr.alt #removed {background-color:#f7cccc;}
  #copied {background-color:#ccccff;}
  tr.alt #copied {background-color:#bbbbf7;}
  #info {color:#888888;}
  #context {background-color:#eeeeee;}
  td {padding-left:.3em;padding-right:.3em;}
  tr.head {border-bottom-width:1px;border-bottom-style:solid;}
  tr.head td {padding:0;padding-top:.2em;}
  .task {background-color:#ffff00;}
  .comment {white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd}
  .error {color:red;}
  hr {border-width:0px;height:2px;background:black;}
--></style>
</head>
<body>
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head"><td colspan="5">Commit in <b><tt>metaas/trunk/src</tt></b></td></tr>
<tr><td><tt>main/antlr/org/asdt/core/internal/antlr/<a href="#file1">AS3.g3</a></tt> </td><td></td><td align="right" id="added">+38</td><td align="right" id="removed">-3</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr class="alt"><td><tt>main/java/uk/co/badgersinfoil/metaas/impl/<a href="#file2"><span id="added">ASTASForStatement.java</span></a></tt> </td><td></td><td align="right" id="added">+153</td><td></td><td nowrap="nowrap" align="right">added 382</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file3">ASTASIfStatement.java</a></tt> </td><td></td><td align="right" id="added">+11</td><td align="right" id="removed">-1</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr class="alt"><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file4">ASTASMethod.java</a></tt> </td><td></td><td align="right" id="added">+2</td><td align="right" id="removed">-1</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file5">ASTFactory.java</a></tt> </td><td></td><td align="right" id="added">+14</td><td align="right" id="removed">-14</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr class="alt"><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file6">ASTStatementList.java</a></tt> </td><td></td><td align="right" id="added">+3</td><td align="right" id="removed">-2</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file7">ASTUtils.java</a></tt> </td><td></td><td align="right" id="added">+19</td><td align="right" id="removed">-1</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr class="alt"><td><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<a href="#file8">TokenBuilder.java</a></tt> </td><td></td><td align="right" id="added">+6</td><td></td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr><td><tt>main/java/uk/co/badgersinfoil/metaas/impl/antlr/<a href="#file9">BasicListUpdateDelegate.java</a></tt> </td><td></td><td align="right" id="added">+43</td><td align="right" id="removed">-6</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr class="alt"><td><tt>test/java/uk/co/badgersinfoil/metaas/<a href="#file10">StatementTests.java</a></tt> </td><td></td><td align="right" id="added">+50</td><td align="right" id="removed">-5</td><td nowrap="nowrap" align="center">381 -&gt; 382</td></tr>
<tr><td></td><td></td><td align="right" id="added">+339</td><td align="right" id="removed">-33</td><td></td></tr>
</table>
<small id="info">1 added + 9 modified, total 10 files</small><br />
<div class="tasklist"><ul>
<li><a href="#task1">TODO: delete PLACEHOLDER tokens when they are superseded by the addition of real tokens</a></li>
</ul></div>
<pre class="comment">
Improved API to handle if-statements and for-statements.
'Placeholder' tokens introduced to help the implementation manage for-statements
look like the way forward, but support needs to be rolled out thoughout the codebase.
</pre>
<hr /><a name="file1" /><div class="file">
<span class="pathname">metaas/trunk/src/main/antlr/org/asdt/core/internal/antlr</span><br />
<div class="fileheader"><big><b>AS3.g3</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/antlr/org/asdt/core/internal/antlr/AS3.g3        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/antlr/org/asdt/core/internal/antlr/AS3.g3        2007-02-04 22:54:55 UTC (rev 382)
@@ -62,6 +62,8 @@
</small></pre><pre class="diff" id="context">         SWITCH_STATEMENT_LIST;
         IDENTIFIER;
         DEFAULT_XML_NAMESPACE;
</pre><pre class="diff" id="added">+        
+        VIRTUAL_PLACEHOLDER;
</pre><pre class="diff" id="context"> }
 
 scope InOperator {
</pre><pre class="diff"><small id="info">@@ -81,6 +83,7 @@
</small></pre><pre class="diff" id="context"> import java.io.IOException;
 import uk.co.badgersinfoil.metaas.impl.parser.E4XHelper;
 import uk.co.badgersinfoil.metaas.impl.parser.RegexSimpleHelper;
</pre><pre class="diff" id="added">+import uk.co.badgersinfoil.metaas.impl.TokenBuilder;
</pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.impl.ASTUtils;
 }
 @lexer::header {
</pre><pre class="diff"><small id="info">@@ -92,6 +95,8 @@
</small></pre><pre class="diff" id="context"> 
 @parser::members {
 
</pre><pre class="diff" id="added">+        public static final int CHANNEL_PLACEHOLDER = 999;
+
</pre><pre class="diff" id="context">         protected void mismatch(IntStream input, int ttype, BitSet follow)
                 throws RecognitionException
         {
</pre><pre class="diff"><small id="info">@@ -128,6 +133,36 @@
</small></pre><pre class="diff" id="context">                 }
                 return tok.getType() == NL;
         }
</pre><pre class="diff" id="added">+        
+        /**
+         * Adds a placeholder token into the stream, corresponding to the
+         * location of the given AST node, if the given AST node has no
+         * children.  Only use this function with 'imaginary' nodes, not with
+         * nodes that already correspond to a concrete Token.
+         */
+        private void placeholder(LinkedListTree imaginary) {
+                if (imaginary.getChildCount() &gt; 0) {
+                        // one of this node's children will presumably have
+                        // some tokens of its own, so there's no need for us
+                        // to synthesize one,
+                        return;
+                }
+
+                // Since this this AST node is 'imaginary', it does not directly
+                // correspond to any Token in the input stream.  Also, since
+                // it has no children, there is nothing anchoring it to a
+                // position in the token-stream, which will make it difficult to
+                // know where new tokens should be inserted if the calling app
+                // adds a child to this node.  We therefore insert a virtual
+                // token at this point in the stream just so that the AST node
+                // can remember its own location.
+
+                LinkedListToken tok = (LinkedListToken)input.LT(1);
+                LinkedListToken placeholder = TokenBuilder.newPlaceholder();
+                tok.beforeInsert(placeholder);
+                imaginary.setStartToken(placeholder);
+                imaginary.setStopToken(placeholder);
+        }
</pre><pre class="diff" id="context"> }
 
 
</pre><pre class="diff"><small id="info">@@ -533,9 +568,9 @@
</small></pre><pre class="diff" id="context">                 statement                                         // statement to loop over
         
 traditionalForClause
</pre><pre class="diff" id="removed">-        :        forInit SEMI!        // initializer
-                forCond SEMI!        // condition test
-                forIter                        // updater
</pre><pre class="diff" id="added">+        :        a=forInit {placeholder($a.tree);} SEMI!        // initializer
+                b=forCond {placeholder($b.tree);} SEMI!        // condition test
+                c=forIter {placeholder($c.tree);}                // updater
</pre><pre class="diff" id="context">         
 
 forInClause
</pre></div>
<hr /><a name="file2" /><div class="file">
<span class="pathname" id="added">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader" id="added"><big><b>ASTASForStatement.java</b></big> <small id="info">added at 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTASForStatement.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTASForStatement.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -0,0 +1,153 @@
</small></pre><pre class="diff" id="added">+/**
+ * ASTASForStatement.java
+ * 
+ * Copyright (c) 2006 David Holroyd
+ */
+
+package uk.co.badgersinfoil.metaas.impl;
+
+import uk.co.badgersinfoil.metaas.dom.ASForStatement;
+import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
+import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
+import uk.co.badgersinfoil.metaas.dom.StatementContainer;
+import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree;
+
+
+public class ASTASForStatement implements ASForStatement {
+
+        private static final int INDEX_INIT = 0;
+        private static final int INDEX_CONDITION = 1;
+        private static final int INDEX_UPDATE = 2;
+        private static final int INDEX_STATEMENT = 3;
+        private LinkedListTree ast;
+
+        public ASTASForStatement(LinkedListTree ast) {
+                this.ast = ast;
+        }
+
+        public String getInitString() {
+                if (!hasInit()) {
+                        return null;
+                }
+                return ASTUtils.stringifyNode(findInit());
+        }
+
+        public String getConditionString() {
+                if (!hasCondition()) {
+                        return null;
+                }
+                return ASTUtils.stringifyNode(findCondition());
+        }
+
+        public String getUpdateString() {
+                if (!hasUpdate()) {
+                        return null;
+                }
+                return ASTUtils.stringifyNode(findUpdate());
+        }
+
+        private boolean hasCondition() {
+                return findCondition().getChildCount() &gt; 0;
+        }
+
+        private boolean hasInit() {
+                return findInit().getChildCount() &gt; 0;
+        }
+
+        private boolean hasUpdate() {
+                return findUpdate().getChildCount() &gt; 0;
+        }
+
+        private LinkedListTree getChild(int index) {
+                return (LinkedListTree)ast.getChild(index);
+        }
+
+        private StatementContainer getBlock() {
+                return new ASTStatementList(getChild(INDEX_STATEMENT));
+        }
+
+        private LinkedListTree findInit() {
+                return getChild(INDEX_INIT);
+        }
+
+        private LinkedListTree findCondition() {
+                return getChild(INDEX_CONDITION);
+        }
+
+        private LinkedListTree findUpdate() {
+                return getChild(INDEX_UPDATE);
+        }
+
+        public void addStmt(String statement) {
+                getBlock().addStmt(statement);
+        }
+
+        public void addComment(String text) {
+                getBlock().addComment(text);
+        }
+
+        public ASIfStatement newIf(String condition) {
+                return getBlock().newIf(condition);
+        }
+
+        public ASForStatement newFor(String init, String condition, String update) {
+                return getBlock().newFor(init, condition, update);
+        }
+
+        public StatementContainer newForIn(String init, String list) {
+                return getBlock().newForIn(init, list);
+        }
+
+        public StatementContainer newForEachIn(String init, String list) {
+                return getBlock().newForEachIn(init, list);
+        }
+
+        public StatementContainer newWhile(String condition) {
+                return getBlock().newWhile(condition);
+        }
+
+        public StatementContainer newDoWhile(String condition) {
+                return getBlock().newDoWhile(condition);
+        }
+
+        public ASSwitchStatement newSwitch(String condition) {
+                return getBlock().newSwitch(condition);
+        }
+
+        public boolean containsCode() {
+                return getBlock().containsCode();
+        }
+
+        public void setCondition(String expr) {
+                if (expr == null) {
+                        deleteAnyChild(findCondition());
+                } else {
+                        LinkedListTree cond = AS3FragmentParser.parseForCond(expr);
+                        ast.setChildWithTokens(INDEX_CONDITION, cond);
+                }
+        }
+
+        public void setInit(String expr) {
+                if (expr == null) {
+                        deleteAnyChild(findInit());
+                } else {
+                        LinkedListTree init = AS3FragmentParser.parseForInit(expr);
+                        ast.setChildWithTokens(INDEX_INIT, init);
+                }
+        }
+
+        public void setUpdate(String expr) {
+                if (expr == null) {
+                        deleteAnyChild(findUpdate());
+                } else {
+                        LinkedListTree update = AS3FragmentParser.parseForIter(expr);
+                        ast.setChildWithTokens(INDEX_UPDATE, update);
+                }
+        }
+
+        private void deleteAnyChild(LinkedListTree tree) {
+                if (tree.getChildCount() &gt; 0) {
+                        tree.deleteChild(0);
+                }
+        }
+}
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file3" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTASIfStatement.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTASIfStatement.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTASIfStatement.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -8,6 +8,7 @@
</small></pre><pre class="diff" id="context"> 
 import org.asdt.core.internal.antlr.AS3Parser;
 import uk.co.badgersinfoil.metaas.dom.ASBlock;
</pre><pre class="diff" id="added">+import uk.co.badgersinfoil.metaas.dom.ASForStatement;
</pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
 import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
 import uk.co.badgersinfoil.metaas.dom.StatementContainer;
</pre><pre class="diff"><small id="info">@@ -54,7 +55,7 @@
</small></pre><pre class="diff" id="context">                 return getThen().newIf(condition);
         }
 
</pre><pre class="diff" id="removed">-        public <span id="removedchars">StatementContainer</span> newFor(String init, String condition,        String update) {
</pre><pre class="diff" id="added">+        public <span id="addedchars">ASForStatement</span> newFor(String init, String condition,        String update) {
</pre><pre class="diff" id="context">                 return getThen().newFor(init, condition, update);
         }
 
</pre><pre class="diff"><small id="info">@@ -91,4 +92,13 @@
</small></pre><pre class="diff" id="context">                 String indent = ASTUtils.findIndent(ast);
                 ASTUtils.increaseIndentAfterFirstLine(theBlock, indent);
         }
</pre><pre class="diff" id="added">+
+        public String getConditionString() {
+                return ASTUtils.stringifyNode(ast.getFirstChild().getFirstChild());
+        }
+
+        public void setCondition(String expr) {
+                LinkedListTree cond = AS3FragmentParser.parseCondition(expr);
+                ast.setChildWithTokens(0, cond);
+        }
</pre><pre class="diff" id="context"> }
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file4" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTASMethod.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTASMethod.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTASMethod.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -12,6 +12,7 @@
</small></pre><pre class="diff" id="context"> import org.asdt.core.internal.antlr.AS3Parser;
 import uk.co.badgersinfoil.metaas.SyntaxException;
 import uk.co.badgersinfoil.metaas.dom.ASArg;
</pre><pre class="diff" id="added">+import uk.co.badgersinfoil.metaas.dom.ASForStatement;
</pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
 import uk.co.badgersinfoil.metaas.dom.ASMethod;
 import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
</pre><pre class="diff"><small id="info">@@ -170,7 +171,7 @@
</small></pre><pre class="diff" id="context">                 return stmtList.newIf(condition);
         }
 
</pre><pre class="diff" id="removed">-        public <span id="removedchars">StatementContainer</span> newFor(String init, String condition, String update) {
</pre><pre class="diff" id="added">+        public <span id="addedchars">ASForStatement</span> newFor(String init, String condition, String update) {
</pre><pre class="diff" id="context">                 return stmtList.newFor(init, condition, update);
         }
 
</pre></div>
<hr /><a name="file5" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTFactory.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTFactory.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTFactory.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -25,7 +25,7 @@
</small></pre><pre class="diff" id="context">         }
 
         public static AS3ASTCompilationUnit synthesizeClass(String qualifiedName) {
</pre><pre class="diff" id="removed">-                LinkedListTree unit = ASTUtils.newAST(AS3Parser.COMPILATION_UNIT);
</pre><pre class="diff" id="added">+                LinkedListTree unit = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.COMPILATION_UNIT);
</pre><pre class="diff" id="context">                 LinkedListTree pkg = ASTUtils.newAST(AS3Parser.PACKAGE, "package");
                 pkg.appendToken(TokenBuilder.newSpace());
                 unit.addChildWithTokens(pkg);
</pre><pre class="diff"><small id="info">@@ -43,7 +43,7 @@
</small></pre><pre class="diff" id="context">         }
 
         public static ASCompilationUnit synthesizeInterface(String qualifiedName) {
</pre><pre class="diff" id="removed">-                LinkedListTree unit = ASTUtils.newAST(AS3Parser.COMPILATION_UNIT);
</pre><pre class="diff" id="added">+                LinkedListTree unit = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.COMPILATION_UNIT);
</pre><pre class="diff" id="context">                 LinkedListTree pkg = ASTUtils.newAST(AS3Parser.PACKAGE, "package");
                 unit.addChildWithTokens(pkg);
                 String packageName = packageNameFrom(qualifiedName);
</pre><pre class="diff"><small id="info">@@ -59,11 +59,11 @@
</small></pre><pre class="diff" id="context">         }
 
         private static LinkedListTree synthesizeAS3Interface(String qualifiedName) {
</pre><pre class="diff" id="removed">-                LinkedListTree iface = ASTUtils.newAST(AS3Parser.INTERFACE_DEF);
-                LinkedListTree annos = ASTUtils.newAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="added">+                LinkedListTree iface = ASTUtils.newImaginaryAST(AS3Parser.INTERFACE_DEF);
+                LinkedListTree annos = ASTUtils.newImaginaryAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="context">                 annos.appendToken(TokenBuilder.newNewline());
                 iface.addChildWithTokens(annos);
</pre><pre class="diff" id="removed">-                LinkedListTree modifiers = ASTUtils.newAST(AS3Parser.MODIFIERS);
</pre><pre class="diff" id="added">+                LinkedListTree modifiers = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.MODIFIERS);
</pre><pre class="diff" id="context">                 iface.addChildWithTokens(modifiers);
                 modifiers.addChildWithTokens(ASTUtils.newAST(AS3Parser.PUBLIC, "public"));
                 modifiers.appendToken(TokenBuilder.newSpace());
</pre><pre class="diff"><small id="info">@@ -85,11 +85,11 @@
</small></pre><pre class="diff" id="context">         }
 
         private static LinkedListTree synthesizeAS3Class(String className) {
</pre><pre class="diff" id="removed">-                LinkedListTree clazz = ASTUtils.newAST(AS3Parser.CLASS_DEF);
-                LinkedListTree annos = ASTUtils.newAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="added">+                LinkedListTree clazz = ASTUtils.newImaginaryAST(AS3Parser.CLASS_DEF);
+                LinkedListTree annos = ASTUtils.newImaginaryAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="context">                 annos.appendToken(TokenBuilder.newNewline());
                 clazz.addChildWithTokens(annos);
</pre><pre class="diff" id="removed">-                LinkedListTree modifiers = ASTUtils.newAST(AS3Parser.MODIFIERS);
</pre><pre class="diff" id="added">+                LinkedListTree modifiers = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.MODIFIERS);
</pre><pre class="diff" id="context">                 clazz.addChildWithTokens(modifiers);
                 LinkedListTree modPublic = ASTUtils.newAST(AS3Parser.PUBLIC, "public");
                 modifiers.addChildWithTokens(modPublic);
</pre><pre class="diff"><small id="info">@@ -116,7 +116,7 @@
</small></pre><pre class="diff" id="context"> 
         public static ASTASMethod newClassMethod(String name, Visibility visibility, String returnType) {
                 LinkedListTree def = ASTUtils.newImaginaryAST(AS3Parser.METHOD_DEF);
</pre><pre class="diff" id="removed">-                LinkedListTree annos = ASTUtils.newAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="added">+                LinkedListTree annos = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="context">                 def.addChildWithTokens(annos);
                 def.addChildWithTokens(ASTUtils.toModifiers(visibility));
                 LinkedListTree decl = ASTUtils.newAST(AS3Parser.FUNCTION, "function");
</pre><pre class="diff"><small id="info">@@ -140,7 +140,7 @@
</small></pre><pre class="diff" id="context">                         throw new SyntaxException("field name must not contain '.'");
                 }
                 LinkedListTree decl = ASTUtils.newImaginaryAST(AS3Parser.VAR_DEF);
</pre><pre class="diff" id="removed">-                LinkedListTree annos = ASTUtils.newAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="added">+                LinkedListTree annos = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="context">                 decl.addChildWithTokens(annos);
                 decl.addChildWithTokens(ASTUtils.toModifiers(visibility));
                 decl.addChildWithTokens(ASTUtils.newAST(AS3Parser.VAR, "var"));
</pre><pre class="diff"><small id="info">@@ -156,7 +156,7 @@
</small></pre><pre class="diff" id="context"> 
         public static ASTASMethod newInterfaceMethod(String name, Visibility visibility, String returnType) {
                 LinkedListTree def = ASTUtils.newImaginaryAST(AS3Parser.METHOD_DEF);
</pre><pre class="diff" id="removed">-                LinkedListTree annos = ASTUtils.newAST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="added">+                LinkedListTree annos = ASTUtils.new<span id="addedchars">Imaginary</span>AST(AS3Parser.ANNOTATIONS);
</pre><pre class="diff" id="context">                 def.addChildWithTokens(annos);
                 def.addChildWithTokens(ASTUtils.toModifiers(visibility));
                 LinkedListTree decl = ASTUtils.newAST(AS3Parser.FUNCTION, "function");
</pre><pre class="diff"><small id="info">@@ -207,7 +207,7 @@
</small></pre><pre class="diff" id="context">                 if (init != null) {
                         forStmt.addChildWithTokens(AS3FragmentParser.parseForInit(init));
                 } else {
</pre><pre class="diff" id="removed">-                        LinkedListTree initStmt = ASTUtils.newAST(AS3Parser.FOR_INIT);
</pre><pre class="diff" id="added">+                        LinkedListTree initStmt = ASTUtils.new<span id="addedchars">Placeholder</span>AST(AS3Parser.FOR_INIT);
</pre><pre class="diff" id="context">                         forStmt.addChildWithTokens(initStmt);
                 }
                 forStmt.appendToken(TokenBuilder.newSemi());
</pre><pre class="diff"><small id="info">@@ -215,7 +215,7 @@
</small></pre><pre class="diff" id="context">                 if (condition != null) {
                         forStmt.addChildWithTokens(AS3FragmentParser.parseForCond(condition));
                 } else {
</pre><pre class="diff" id="removed">-                        LinkedListTree condStmt = ASTUtils.newAST(AS3Parser.FOR_CONDITION);
</pre><pre class="diff" id="added">+                        LinkedListTree condStmt = ASTUtils.new<span id="addedchars">Placeholder</span>AST(AS3Parser.FOR_CONDITION);
</pre><pre class="diff" id="context">                         forStmt.addChildWithTokens(condStmt);
                 }
                 forStmt.appendToken(TokenBuilder.newSemi());
</pre><pre class="diff"><small id="info">@@ -223,7 +223,7 @@
</small></pre><pre class="diff" id="context">                 if (iterate != null) {
                         forStmt.addChildWithTokens(AS3FragmentParser.parseForIter(iterate));
                 } else {
</pre><pre class="diff" id="removed">-                        LinkedListTree iterStmt = ASTUtils.newAST(AS3Parser.FOR_ITERATOR);
</pre><pre class="diff" id="added">+                        LinkedListTree iterStmt = ASTUtils.new<span id="addedchars">Placeholder</span>AST(AS3Parser.FOR_ITERATOR);
</pre><pre class="diff" id="context">                         forStmt.addChildWithTokens(iterStmt);
                 }
                 forStmt.appendToken(TokenBuilder.newRParen());
</pre></div>
<hr /><a name="file6" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTStatementList.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTStatementList.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTStatementList.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -8,6 +8,7 @@
</small></pre><pre class="diff" id="context"> 
 import org.asdt.core.internal.antlr.AS3Parser;
 import uk.co.badgersinfoil.metaas.dom.ASBlock;
</pre><pre class="diff" id="added">+import uk.co.badgersinfoil.metaas.dom.ASForStatement;
</pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
 import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
 import uk.co.badgersinfoil.metaas.dom.StatementContainer;
</pre><pre class="diff"><small id="info">@@ -57,11 +58,11 @@
</small></pre><pre class="diff" id="context">                 return new ASTASIfStatement(ifStmt);
         }
 
</pre><pre class="diff" id="removed">-        public <span id="removedchars">StatementContainer</span> newFor(String init, String condition, String iterate) {
</pre><pre class="diff" id="added">+        public <span id="addedchars">ASForStatement</span> newFor(String init, String condition, String iterate) {
</pre><pre class="diff" id="context">                 LinkedListTree forStmt = ASTFactory.newFor(init, condition, iterate);
                 addStatement(forStmt);
                 LinkedListTree block = appendBlock(forStmt);
</pre><pre class="diff" id="removed">-                return new ASTStatementList(block);
</pre><pre class="diff" id="added">+                return new ASTASForStatement(forStmt);
</pre><pre class="diff" id="context">         }
 
         public StatementContainer newForIn(String declaration, String expression) {
</pre></div>
<hr /><a name="file7" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>ASTUtils.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTUtils.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/ASTUtils.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -198,12 +198,19 @@
</small></pre><pre class="diff" id="context">         /**
          * Constructs a new AST of the given type, initialized to contain
          * text matching the token's name (use for non-literals only).
</pre><pre class="diff" id="removed">-         * @deprecated
</pre><pre class="diff" id="context">          */
         public static LinkedListTree newImaginaryAST(int type) {
                 return (LinkedListTree)TREE_ADAPTOR.create(type, tokenName(type));
         }
 
</pre><pre class="diff" id="added">+        public static LinkedListTree newPlaceholderAST(int type) {
+                LinkedListTree node = newImaginaryAST(type);
+                LinkedListToken placeholder = TokenBuilder.newPlaceholder();
+                node.setStartToken(placeholder);
+                node.setStopToken(placeholder);
+                return node;
+        }
+
</pre><pre class="diff" id="context">         /**
          * Constructs a new AST of the given type, initialized to contain the
          * given text.
</pre><pre class="diff"><small id="info">@@ -408,4 +415,15 @@
</small></pre><pre class="diff" id="context">                         throw new SyntaxException("Expected "+tokenName(expected)+", got "+tokenName(actual));
                 }
         }
</pre><pre class="diff" id="added">+        
+        public static String stringifyNode(LinkedListTree ast) {
+                StringBuffer result = new StringBuffer();
+                for (LinkedListToken tok=ast.getStartToken(); tok!=null; tok=tok.getNext()) {
+                        result.append(tok.getText());
+                        if (tok == ast.getStopToken()) {
+                                break;
+                        }
+                }
+                return result.toString();
+        }
</pre><pre class="diff" id="context"> }
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file8" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl</span><br />
<div class="fileheader"><big><b>TokenBuilder.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/TokenBuilder.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/TokenBuilder.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -91,4 +91,10 @@
</small></pre><pre class="diff" id="context">         public static LinkedListToken newInterface() {
                 return newToken(AS3Parser.INTERFACE, "interface");
         }
</pre><pre class="diff" id="added">+        
+        public static LinkedListToken newPlaceholder() {
+                LinkedListToken placeholder = new LinkedListToken(AS3Parser.VIRTUAL_PLACEHOLDER, "");
+                placeholder.setChannel(AS3Parser.CHANNEL_PLACEHOLDER);
+                return placeholder;
+        }
</pre><pre class="diff" id="context"> }
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file9" /><div class="file">
<span class="pathname">metaas/trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/antlr</span><br />
<div class="fileheader"><big><b>BasicListUpdateDelegate.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/antlr/BasicListUpdateDelegate.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/main/java/uk/co/badgersinfoil/metaas/impl/antlr/BasicListUpdateDelegate.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -4,6 +4,7 @@
</small></pre><pre class="diff" id="context"> 
 package uk.co.badgersinfoil.metaas.impl.antlr;
 
</pre><pre class="diff" id="added">+import uk.co.badgersinfoil.metaas.impl.TokenBuilder;
</pre><pre class="diff" id="context"> 
 /**
  * Manages the tokens of the parent tree in the most basic way possible, simply
</pre><pre class="diff"><small id="info">@@ -12,6 +13,9 @@
</small></pre><pre class="diff" id="context">  * required.
  */
 public class BasicListUpdateDelegate implements TreeTokenListUpdateDelegate {
</pre><pre class="diff" id="added">+
<a name="task1" />+        // <span class="task">TODO</span>: delete PLACEHOLDER tokens when they are superseded by the addition of real tokens
+
</pre><pre class="diff" id="context">         public void addedChild(LinkedListTree parent, LinkedListTree child) {
                 LinkedListToken stop = findTokenInsertionPointForChildWithinParent(parent, child);
                 if (parent.getStartToken() == null) {
</pre><pre class="diff"><small id="info">@@ -148,10 +152,27 @@
</small></pre><pre class="diff" id="context">                 if (stopNext == null) {
                         throw new IllegalArgumentException("No stop.next: "+child+" (stop="+stop+")");
                 }
</pre><pre class="diff" id="removed">-                if (startPrev != null) {
-                        startPrev.setNext(stopNext);
-                } else if (stopNext != null) {  // so try the other way around,
-                        stopNext.setPrev(startPrev);
</pre><pre class="diff" id="added">+                if (parent.getChildCount() == 0
+                 &amp;&amp; start == parent.getStartToken()
+                 &amp;&amp; stop == parent.getStopToken())
+                {
+                        // So, the child provided all the tokens that made up
+                        // the parent, and removing it will leave nothing!  In
+                        // this case, we insert a 'placeholder' token just so
+                        // there's something in the token stream for the parent
+                        // to reference, and the parent remains anchored to the
+                        // appropriate location within the source code
+                        LinkedListToken placeholder = TokenBuilder.newPlaceholder();
+                        startPrev.setNext(placeholder);
+                        stopNext.setPrev(placeholder);
+                        parent.setStartToken(placeholder);
+                        parent.setStopToken(placeholder);
+                } else {
+                        if (startPrev != null) {
+                                startPrev.setNext(stopNext);
+                        } else if (stopNext != null) {  // so try the other way around,
+                                stopNext.setPrev(startPrev);
+                        }
</pre><pre class="diff" id="context">                 }
                 // just to save possible confusion, break links out from the
                 // removed token list too,
</pre><pre class="diff"><small id="info">@@ -168,8 +189,8 @@
</small></pre><pre class="diff" id="context">                         throw new IllegalArgumentException("No stopToken: "+child);
                 }
                 // link the new child's tokens in place of the old,
</pre><pre class="diff" id="removed">-                LinkedListToken oldBefore = oldChild.getStartToken().getPrev();
-                LinkedListToken oldAfter = oldChild.getStopToken().getNext();
</pre><pre class="diff" id="added">+                LinkedListToken oldBefore = findOldBeforeToken(tree, index, child, oldChild);
+                LinkedListToken oldAfter = findOldAfterToken(tree, index, child, oldChild);
</pre><pre class="diff" id="context">                 oldBefore.setNext(child.getStartToken());
                 oldAfter.setPrev(child.getStopToken());
                 // just to save possible confusion, break links out from the
</pre><pre class="diff"><small id="info">@@ -184,4 +205,20 @@
</small></pre><pre class="diff" id="context">                         tree.setStopToken(child.getStopToken());
                 }
         }
</pre><pre class="diff" id="added">+
+        private LinkedListToken findOldBeforeToken(LinkedListTree tree, int index, LinkedListTree child, LinkedListTree oldChild) {
+                LinkedListToken oldStart = oldChild.getStartToken();
+                if (oldStart == null) {
+                        throw new IllegalStateException("&lt;"+oldChild+"&gt;, child "+index+" of &lt;"+tree+"&gt;, had no startToken");
+                }
+                return oldStart.getPrev();
+        }
+
+        private LinkedListToken findOldAfterToken(LinkedListTree tree, int index, LinkedListTree child, LinkedListTree oldChild) {
+                LinkedListToken oldStop = oldChild.getStopToken();
+                if (oldStop == null) {
+                        throw new IllegalStateException("&lt;"+oldChild+"&gt;, child "+index+" of &lt;"+tree+"&gt;, had no stopToken");
+                }
+                return oldStop.getNext();
+        }
</pre><pre class="diff" id="context"> }
</pre><pre class="diff"><small id="info">\ No newline at end of file
</small></pre></div>
<hr /><a name="file10" /><div class="file">
<span class="pathname">metaas/trunk/src/test/java/uk/co/badgersinfoil/metaas</span><br />
<div class="fileheader"><big><b>StatementTests.java</b></big> <small id="info">381 -&gt; 382</small></div>
<pre class="diff"><small id="info">--- trunk/src/test/java/uk/co/badgersinfoil/metaas/StatementTests.java        2007-02-04 16:01:29 UTC (rev 381)
+++ trunk/src/test/java/uk/co/badgersinfoil/metaas/StatementTests.java        2007-02-04 22:54:55 UTC (rev 382)
@@ -4,6 +4,7 @@
</small></pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.dom.ASBlock;
 import uk.co.badgersinfoil.metaas.dom.ASClassType;
 import uk.co.badgersinfoil.metaas.dom.ASCompilationUnit;
</pre><pre class="diff" id="added">+import uk.co.badgersinfoil.metaas.dom.ASForStatement;
</pre><pre class="diff" id="context"> import uk.co.badgersinfoil.metaas.dom.ASIfStatement;
 import uk.co.badgersinfoil.metaas.dom.ASMethod;
 import uk.co.badgersinfoil.metaas.dom.ASSwitchStatement;
</pre><pre class="diff"><small id="info">@@ -30,31 +31,75 @@
</small></pre><pre class="diff" id="context"> 
         public void testStatements() throws IOException {
                 meth.setDocComment("\n doc\n comment!\n");
</pre><pre class="diff" id="added">+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="removed">-                StatementContainer block;
</pre><pre class="diff" id="added">+        public void testExpressionStatement() {
+                meth.addStmt("a=1");
+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="added">+        public void testIfStatement() {
</pre><pre class="diff" id="context">                 ASIfStatement ifStmt = meth.newIf("a == b");
                 ifStmt.addStmt("trace('then true!')");
                 ifStmt.getElse().addStmt("trace('else false!')");
</pre><pre class="diff" id="added">+                assertEquals("a == b", ifStmt.getConditionString());
+                ifStmt.setCondition("b == a");
+                assertEquals("b == a", ifStmt.getConditionString());
+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="removed">-                block = meth.newFor(null, null, null);
-                block.addStmt("trace(\"forever\")");
</pre><pre class="diff" id="added">+        public void testFor() {
+                ASForStatement forStmt = meth.newFor(null, null, null);
+                forStmt.addStmt("trace(\"forever\")");
+                assertNull(forStmt.getInitString());
+                assertNull(forStmt.getConditionString());
+                assertNull(forStmt.getUpdateString());
+                forStmt.setInit("var j");
+                forStmt.setCondition("j&lt;10");
+                forStmt.setUpdate("j++");
+                assertEquals("var j", forStmt.getInitString());
+                assertEquals("j&lt;10", forStmt.getConditionString());
+                assertEquals("j++", forStmt.getUpdateString());
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="removed">-                block = meth.newFor("var i", "i&lt;10", "i++");
-                block.addStmt("trace(i)");
</pre><pre class="diff" id="added">+                forStmt = meth.newFor("var i", "i&lt;10", "i++");
+                forStmt.addStmt("trace(i)");
+                assertEquals("var i", forStmt.getInitString());
+                assertEquals("i&lt;10", forStmt.getConditionString());
+                assertEquals("i++", forStmt.getUpdateString());
+                forStmt.setInit(null);
+                forStmt.setCondition(null);
+                forStmt.setUpdate(null);
+                assertNull(forStmt.getInitString());
+                assertNull(forStmt.getConditionString());
+                assertNull(forStmt.getUpdateString());
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="added">+                forStmt.setInit("var k=0");
+                assertEquals("var k=0", forStmt.getInitString());
+        }
+
+        public void testForIn() {
+                StatementContainer block;
</pre><pre class="diff" id="context">                 block = meth.newForIn("var i", "arry");
                 block.addStmt("trace(i)");
</pre><pre class="diff" id="added">+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="added">+        public void testForEachIn() {
+                StatementContainer block;
</pre><pre class="diff" id="context">                 block = meth.newForEachIn("var i", "arry");
                 block.addStmt("trace(i)");
</pre><pre class="diff" id="added">+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="added">+        public void testWhile() {
+                StatementContainer block;
</pre><pre class="diff" id="context">                 block = meth.newWhile("test()");
                 block.addStmt("trace(result())");
</pre><pre class="diff" id="added">+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="added">+        public void testDoWhile() {
+                StatementContainer block;
</pre><pre class="diff" id="context">                 block = meth.newDoWhile("test()");
                 block.addStmt("trace(result())");
</pre><pre class="diff" id="added">+        }
</pre><pre class="diff" id="context"> 
</pre><pre class="diff" id="added">+        public void testSwitch() {
</pre><pre class="diff" id="context">                 ASSwitchStatement swtch = meth.newSwitch("foo");
                 StatementContainer cas = swtch.newCase("1");
                 assertFalse("Empty case statement claims to contain code", cas.containsCode());
</pre></div>
<center><small><a href="http://www.badgers-in-foil.co.uk/projects/cvsspam/" title="commit -&gt; email">CVSspam</a> 0.2.12</small></center>
</body></html>