Author: ihab.awad
Date: Wed Jul 15 11:24:34 2009
New Revision: 3574

Modified:
   trunk/src/com/google/caja/parser/ParseTreeNode.java
   trunk/src/com/google/caja/parser/ParseTreeNodeContainer.java
   trunk/src/com/google/caja/parser/ParseTreeNodes.java
   trunk/src/com/google/caja/parser/css/CssTree.java
   trunk/src/com/google/caja/parser/js/AbstractExpression.java
   trunk/src/com/google/caja/parser/js/AbstractStatement.java
   trunk/src/com/google/caja/parser/js/ArrayConstructor.java
   trunk/src/com/google/caja/parser/js/AssignOperation.java
   trunk/src/com/google/caja/parser/js/Block.java
   trunk/src/com/google/caja/parser/js/BooleanLiteral.java
   trunk/src/com/google/caja/parser/js/BreakStmt.java
   trunk/src/com/google/caja/parser/js/CajoledModule.java
   trunk/src/com/google/caja/parser/js/CaseStmt.java
   trunk/src/com/google/caja/parser/js/CatchStmt.java
   trunk/src/com/google/caja/parser/js/Conditional.java
   trunk/src/com/google/caja/parser/js/ContinueStmt.java
   trunk/src/com/google/caja/parser/js/ControlOperation.java
   trunk/src/com/google/caja/parser/js/DebuggerStmt.java
   trunk/src/com/google/caja/parser/js/Declaration.java
   trunk/src/com/google/caja/parser/js/DefaultCaseStmt.java
   trunk/src/com/google/caja/parser/js/DoWhileLoop.java
   trunk/src/com/google/caja/parser/js/ExpressionStmt.java
   trunk/src/com/google/caja/parser/js/FinallyStmt.java
   trunk/src/com/google/caja/parser/js/ForEachLoop.java
   trunk/src/com/google/caja/parser/js/ForLoop.java
   trunk/src/com/google/caja/parser/js/FormalParam.java
   trunk/src/com/google/caja/parser/js/FunctionConstructor.java
   trunk/src/com/google/caja/parser/js/FunctionDeclaration.java
   trunk/src/com/google/caja/parser/js/Identifier.java
   trunk/src/com/google/caja/parser/js/IntegerLiteral.java
   trunk/src/com/google/caja/parser/js/LabeledStmtWrapper.java
   trunk/src/com/google/caja/parser/js/Loop.java
   trunk/src/com/google/caja/parser/js/MultiDeclaration.java
   trunk/src/com/google/caja/parser/js/Noop.java
   trunk/src/com/google/caja/parser/js/NullLiteral.java
   trunk/src/com/google/caja/parser/js/ObjectConstructor.java
   trunk/src/com/google/caja/parser/js/QuotedExpression.java
   trunk/src/com/google/caja/parser/js/RealLiteral.java
   trunk/src/com/google/caja/parser/js/Reference.java
   trunk/src/com/google/caja/parser/js/RegexpLiteral.java
   trunk/src/com/google/caja/parser/js/ReturnStmt.java
   trunk/src/com/google/caja/parser/js/SimpleOperation.java
   trunk/src/com/google/caja/parser/js/SpecialOperation.java
   trunk/src/com/google/caja/parser/js/StringLiteral.java
   trunk/src/com/google/caja/parser/js/SwitchStmt.java
   trunk/src/com/google/caja/parser/js/ThrowStmt.java
   trunk/src/com/google/caja/parser/js/TranslatedCode.java
   trunk/src/com/google/caja/parser/js/TryStmt.java
   trunk/src/com/google/caja/parser/js/UncajoledModule.java
   trunk/src/com/google/caja/parser/js/UseSubset.java
   trunk/src/com/google/caja/parser/js/UseSubsetDirective.java
   trunk/src/com/google/caja/parser/js/WhileLoop.java
   trunk/src/com/google/caja/parser/js/WithStmt.java
   trunk/tests/com/google/caja/parser/css/CssParserTest.java
   trunk/tests/com/google/caja/parser/js/ParserTest.java
   trunk/tests/com/google/caja/util/CajaTestCase.java

Log:
Fix http://code.google.com/p/google-caja/issues/detail?id=985.

Adds more predictability to our reflective ParseTreeNode constructors,
and adds tests of node cloning.


Modified: trunk/src/com/google/caja/parser/ParseTreeNode.java
==============================================================================
--- trunk/src/com/google/caja/parser/ParseTreeNode.java (original)
+++ trunk/src/com/google/caja/parser/ParseTreeNode.java Wed Jul 15 11:24:34 2009
@@ -24,6 +24,11 @@

 import java.io.IOException;
 import java.util.List;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;

 /**
  * A node in a parse tree.
@@ -90,4 +95,14 @@
* @return a deep clone of the node tree rooted at this {...@code ParseTreeNode}.
    */
   ParseTreeNode clone();
+
+  /**
+ * Indicates that the annotated constructor of a {...@code ParseTreeNode} is to + * be used for reflectively constructing a new node or cloning an existing
+   * node.
+   */
+  @Documented
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target(ElementType.CONSTRUCTOR)
+  public @interface ReflectiveCtor { }
 }

Modified: trunk/src/com/google/caja/parser/ParseTreeNodeContainer.java
==============================================================================
--- trunk/src/com/google/caja/parser/ParseTreeNodeContainer.java        
(original)
+++ trunk/src/com/google/caja/parser/ParseTreeNodeContainer.java Wed Jul 15 11:24:34 2009
@@ -33,6 +33,7 @@
  */
 public class ParseTreeNodeContainer extends AbstractParseTreeNode {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ParseTreeNodeContainer(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     super(pos);

Modified: trunk/src/com/google/caja/parser/ParseTreeNodes.java
==============================================================================
--- trunk/src/com/google/caja/parser/ParseTreeNodes.java        (original)
+++ trunk/src/com/google/caja/parser/ParseTreeNodes.java Wed Jul 15 11:24:34 2009
@@ -96,12 +96,23 @@
       Class<?>[] parameterTypes = ctor.getParameterTypes();
       if (parameterTypes.length == 3
           && FilePosition.class.equals(parameterTypes[0])
-          && ctor.getParameterTypes()[2].isAssignableFrom(List.class)) {
+          && ctor.getParameterTypes()[2].isAssignableFrom(List.class)
+          && isReflectiveCtorAnnotated(ctor)) {
         cloneCtorCache.put(clazz, ctor);
         return ctor;
       }
     }
     throw new RuntimeException("Cannot find clone ctor for node " + clazz);
+  }
+
+ private static final boolean isReflectiveCtorAnnotated(Constructor<?> ctor) {
+    for (int i = 0; i < ctor.getDeclaredAnnotations().length; ++i) {
+      if (ctor.getDeclaredAnnotations()[i]
+              instanceof ParseTreeNode.ReflectiveCtor) {
+        return true;
+      }
+    }
+    return false;
   }

   @SuppressWarnings("unchecked")

Modified: trunk/src/com/google/caja/parser/css/CssTree.java
==============================================================================
--- trunk/src/com/google/caja/parser/css/CssTree.java   (original)
+++ trunk/src/com/google/caja/parser/css/CssTree.java Wed Jul 15 11:24:34 2009
@@ -91,6 +91,7 @@
    */
   public static final class StyleSheet extends CssTree {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public StyleSheet(
FilePosition pos, Void novalue, List<? extends CssStatement> rulesets) {
       this(pos, rulesets);
@@ -114,6 +115,7 @@
    */
   public static final class DeclarationGroup extends CssTree {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public DeclarationGroup(
FilePosition pos, Void novalue, List<? extends Declaration> decls) {
       this(pos, decls);
@@ -174,6 +176,13 @@
       return l;
     }

+    /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
+    public Import(
+        FilePosition pos, Void novalue, List<? extends Medium> media) {
+      super(pos, media);
+    }
+
     public Import(
         FilePosition pos, UriLiteral uri, List<? extends Medium> media) {
       super(pos, join(Collections.singletonList(uri), media));
@@ -214,6 +223,7 @@
    */
   public static final class Media extends CssStatement {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public Media(
         FilePosition pos, Void novalue,
         List<? extends CssTree> mediaAndRuleset) {
@@ -261,6 +271,7 @@
     final Name ident;

     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
public Medium(FilePosition pos, Name ident, List<? extends CssTree> none) {
       this(pos, ident);
     }
@@ -288,6 +299,7 @@
   public static final class Page extends CssStatement {
     final Name ident;

+    @ReflectiveCtor
     public Page(
         FilePosition pos, Name ident, List<? extends PageElement> decls) {
       super(pos, decls);
@@ -338,6 +350,7 @@
     final Name ident;

     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public PseudoPage(
         FilePosition pos, Name ident, List<? extends CssTree> none) {
       this(pos, ident);
@@ -366,6 +379,7 @@
    */
   public static final class FontFace extends CssStatement {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public FontFace(
FilePosition pos, Void novalue, List<? extends Declaration> decls) {
       this(pos, decls);
@@ -403,6 +417,7 @@
   public static final class Property extends CssTree {
     private final Name ident;
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public Property(
         FilePosition pos, Name ident, List<? extends CssTree> none) {
       this(pos, ident);
@@ -435,6 +450,7 @@
    */
   public static final class RuleSet extends CssStatement {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public RuleSet(
         FilePosition pos, Void novalue,
         List<? extends CssTree> selectorsAndDecls) {
@@ -469,6 +485,7 @@
    */
   public static final class Selector extends CssTree {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public Selector(
         FilePosition pos, Void novalue, List<? extends CssTree> children) {
       this(pos, children);
@@ -508,6 +525,7 @@
    */
   public static final class SimpleSelector extends CssTree {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public SimpleSelector(
         FilePosition pos, Void novalue, List<? extends CssTree> children) {
       this(pos, children);
@@ -542,6 +560,7 @@
      * @param novalue ignored but required for reflection.
      * @param none ignored but required for reflection.
      */
+    @ReflectiveCtor
     public WildcardElement(
         FilePosition pos, Void novalue, List<? extends CssTree> none) {
       this(pos);
@@ -572,6 +591,7 @@
   public static final class Attrib extends CssTree {
     final String ident;

+    @ReflectiveCtor
     public Attrib(
         FilePosition pos, String ident,
         List<? extends CssTree> operatorAndValue) {
@@ -630,6 +650,7 @@
   public static final class AttribOperation extends CssTree {
     final AttribOperator op;
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public AttribOperation(
FilePosition pos, AttribOperator op, List<? extends CssTree> none) {
       this(pos, op);
@@ -657,6 +678,7 @@
    */
   public static final class Pseudo extends CssTree {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public Pseudo(
FilePosition pos, Void novalue, List<? extends CssExprAtom> oneAtom) {
       this(pos, oneAtom.get(0));
@@ -708,6 +730,7 @@
      * @param novalue ignored but required for reflection.
      * @param none ignored but required for reflection.
      */
+    @ReflectiveCtor
     public EmptyDeclaration(
         FilePosition pos, Void novalue, List<? extends CssTree> none) {
       this(pos);
@@ -735,6 +758,7 @@
     private Prio prio;

     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public PropertyDeclaration(
         FilePosition pos, Void novalue, List<? extends CssTree> children) {
       this(pos, children);
@@ -782,6 +806,7 @@
     final String value;

     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
public Prio(FilePosition pos, String value, List<? extends CssTree> none) {
       this(pos, value);
     }
@@ -809,6 +834,7 @@
    */
   public static final class Expr extends CssTree {
     /** @param novalue ignored but required for reflection. */
+    @ReflectiveCtor
     public Expr(
         FilePosition pos, Void novalue, List<? extends CssTree> children) {
       this(pos, children);
@@ -849,6 +875,7 @@
    */
   public static final class Term extends CssTree {
     private final UnaryOperator op;
+    @ReflectiveCtor
     public Term(FilePosition pos, UnaryOperator op,
                 List<? extends CssExprAtom> oneatom) {
       this(pos, op, oneatom.get(0));
@@ -939,6 +966,7 @@
    */
   public static final class IdLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public IdLiteral(
FilePosition pos, String inputValue, List<? extends CssTree> none) {
       this(pos, inputValue);
@@ -960,6 +988,7 @@
    */
   public static final class ClassLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public ClassLiteral(
FilePosition pos, String inputValue, List<? extends CssTree> none) {
       this(pos, inputValue);
@@ -981,6 +1010,7 @@
    */
   public static final class StringLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public StringLiteral(
FilePosition pos, String inputValue, List<? extends CssTree> none) {
       this(pos, inputValue);
@@ -1001,6 +1031,7 @@
    */
   public static final class HashLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public HashLiteral(
FilePosition pos, String inputValue, List<? extends CssTree> none) {
       this(pos, inputValue);
@@ -1021,6 +1052,7 @@
    */
   public static final class QuantityLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public QuantityLiteral(
FilePosition pos, String inputValue, List<? extends CssTree> none) {
       this(pos, inputValue);
@@ -1043,6 +1075,7 @@
    */
   public static final class UnicodeRangeLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public UnicodeRangeLiteral(
FilePosition pos, String inputValue, List<? extends CssTree> none) {
       this(pos, inputValue);
@@ -1065,9 +1098,10 @@
    */
   public static final class UriLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public UriLiteral(
-        FilePosition pos, URI value, List<? extends CssTree> none) {
-      this(pos, value);
+        FilePosition pos, String value, List<? extends CssTree> none) {
+      this(pos, URI.create(value));
     }
     public UriLiteral(FilePosition pos, URI value) {
       super(pos, value.toString());
@@ -1098,6 +1132,7 @@
    */
   public static final class IdentLiteral extends CssLiteral {
     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public IdentLiteral(
         FilePosition pos, String value, List<? extends CssTree> none) {
       this(pos, value);
@@ -1123,6 +1158,7 @@
    */
   public static final class FunctionCall extends CssExprAtom {
     private final Name name;
+    @ReflectiveCtor
     public FunctionCall(
         FilePosition pos, Name name, List<? extends Expr> expr) {
       this(pos, name, expr.get(0));
@@ -1159,6 +1195,7 @@
   public static final class ProgId extends CssExprAtom {
     private final Name name;

+    @ReflectiveCtor
     public ProgId(
FilePosition pos, Name name, List<? extends ProgIdAttribute> attrs) {
       super(pos, ProgIdAttribute.class, attrs);
@@ -1193,6 +1230,7 @@
   public static final class ProgIdAttribute extends CssTree {
     private final Name name;

+    @ReflectiveCtor
     public ProgIdAttribute(
         FilePosition pos, Name name, List<? extends Term> value) {
       super(pos, Term.class, value);
@@ -1271,6 +1309,7 @@
     final Combinator comb;

     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public Combination(
         FilePosition pos, Combinator comb, List<? extends CssTree> none) {
       this(pos, comb);
@@ -1296,6 +1335,7 @@
     final Operator op;

     /** @param none ignored but required for reflection. */
+    @ReflectiveCtor
     public Operation(
         FilePosition pos, Operator op, List<? extends CssTree> none) {
       this(pos, op);
@@ -1377,6 +1417,7 @@
   public static final class UserAgentHack extends Declaration {
     private final EnumSet<UserAgent> enabledOn;

+    @ReflectiveCtor
     public UserAgentHack(
         FilePosition pos, Set<UserAgent> enabledOn,
         List<? extends PropertyDeclaration> decl) {

Modified: trunk/src/com/google/caja/parser/js/AbstractExpression.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/AbstractExpression.java (original)
+++ trunk/src/com/google/caja/parser/js/AbstractExpression.java Wed Jul 15 11:24:34 2009
@@ -30,6 +30,7 @@
  */
 public abstract class AbstractExpression
     extends AbstractParseTreeNode implements Expression {
+  @ReflectiveCtor
   public AbstractExpression(
       FilePosition pos, Class<? extends ParseTreeNode> childClass) {
     super(pos, childClass);

Modified: trunk/src/com/google/caja/parser/js/AbstractStatement.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/AbstractStatement.java  (original)
+++ trunk/src/com/google/caja/parser/js/AbstractStatement.java Wed Jul 15 11:24:34 2009
@@ -34,6 +34,7 @@
  */
 public abstract class AbstractStatement
     extends AbstractParseTreeNode implements Statement {
+  @ReflectiveCtor
   public AbstractStatement(
       FilePosition pos, Class<? extends ParseTreeNode> childClass) {
     super(pos, childClass);

Modified: trunk/src/com/google/caja/parser/js/ArrayConstructor.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ArrayConstructor.java   (original)
+++ trunk/src/com/google/caja/parser/js/ArrayConstructor.java Wed Jul 15 11:24:34 2009
@@ -27,6 +27,7 @@
  */
 public final class ArrayConstructor extends AbstractExpression {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ArrayConstructor(
       FilePosition pos, Void value, List<? extends Expression> children) {
     this(pos, children);

Modified: trunk/src/com/google/caja/parser/js/AssignOperation.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/AssignOperation.java    (original)
+++ trunk/src/com/google/caja/parser/js/AssignOperation.java Wed Jul 15 11:24:34 2009
@@ -27,6 +27,7 @@
  * @author [email protected]
  */
 public final class AssignOperation extends Operation {
+  @ReflectiveCtor
   public AssignOperation(
FilePosition pos, Operator value, List<? extends Expression> children) {
     super(pos, value, children);

Modified: trunk/src/com/google/caja/parser/js/Block.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Block.java      (original)
+++ trunk/src/com/google/caja/parser/js/Block.java      Wed Jul 15 11:24:34 2009
@@ -30,6 +30,7 @@
 public final class Block
     extends AbstractStatement implements NestedScope {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public Block(
       FilePosition pos, Void value, List<? extends Statement> children) {
     this(pos, children);

Modified: trunk/src/com/google/caja/parser/js/BooleanLiteral.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/BooleanLiteral.java     (original)
+++ trunk/src/com/google/caja/parser/js/BooleanLiteral.java Wed Jul 15 11:24:34 2009
@@ -28,6 +28,7 @@
   public final boolean value;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public BooleanLiteral(
FilePosition pos, Boolean value, List<? extends ParseTreeNode> children) {
     this(pos, value);

Modified: trunk/src/com/google/caja/parser/js/BreakStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/BreakStmt.java  (original)
+++ trunk/src/com/google/caja/parser/js/BreakStmt.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private final String label;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public BreakStmt(
FilePosition pos, String value, List<? extends ParseTreeNode> children) {
     this(pos, value);

Modified: trunk/src/com/google/caja/parser/js/CajoledModule.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/CajoledModule.java      (original)
+++ trunk/src/com/google/caja/parser/js/CajoledModule.java Wed Jul 15 11:24:34 2009
@@ -46,6 +46,7 @@
       new InputSource(URI.create("file:///CAJOLED-OUTPUT"));

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public CajoledModule(FilePosition pos,
                        Void value,
                        List<? extends ObjectConstructor> children) {

Modified: trunk/src/com/google/caja/parser/js/CaseStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/CaseStmt.java   (original)
+++ trunk/src/com/google/caja/parser/js/CaseStmt.java Wed Jul 15 11:24:34 2009
@@ -39,6 +39,7 @@
   private Statement body;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public CaseStmt(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     this(pos, (Expression) children.get(0), (Statement) children.get(1));

Modified: trunk/src/com/google/caja/parser/js/CatchStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/CatchStmt.java  (original)
+++ trunk/src/com/google/caja/parser/js/CatchStmt.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private Statement body;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public CatchStmt(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     this(pos, (Declaration) children.get(0), (Statement) children.get(1));

Modified: trunk/src/com/google/caja/parser/js/Conditional.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Conditional.java        (original)
+++ trunk/src/com/google/caja/parser/js/Conditional.java Wed Jul 15 11:24:34 2009
@@ -29,6 +29,7 @@
  */
 public final class Conditional extends AbstractStatement {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public Conditional(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     super(pos, ParseTreeNode.class);

Modified: trunk/src/com/google/caja/parser/js/ContinueStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ContinueStmt.java       (original)
+++ trunk/src/com/google/caja/parser/js/ContinueStmt.java Wed Jul 15 11:24:34 2009
@@ -30,6 +30,7 @@
   private String label;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ContinueStmt(
       FilePosition pos, String value, List<? extends Statement> children) {
     this(pos, value);

Modified: trunk/src/com/google/caja/parser/js/ControlOperation.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ControlOperation.java   (original)
+++ trunk/src/com/google/caja/parser/js/ControlOperation.java Wed Jul 15 11:24:34 2009
@@ -25,6 +25,7 @@
  * @author [email protected]
  */
 public final class ControlOperation extends Operation {
+  @ReflectiveCtor
   public ControlOperation(
FilePosition pos, Operator value, List<? extends Expression> children) {
     super(pos, value, children);

Modified: trunk/src/com/google/caja/parser/js/DebuggerStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/DebuggerStmt.java       (original)
+++ trunk/src/com/google/caja/parser/js/DebuggerStmt.java Wed Jul 15 11:24:34 2009
@@ -33,6 +33,7 @@
    * @param value unused.
    * @param children unused.
    */
+  @ReflectiveCtor
   public DebuggerStmt(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     super(pos, NoChildren.class);

Modified: trunk/src/com/google/caja/parser/js/Declaration.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Declaration.java        (original)
+++ trunk/src/com/google/caja/parser/js/Declaration.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private Expression initializer;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public Declaration(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     super(pos, ParseTreeNode.class);

Modified: trunk/src/com/google/caja/parser/js/DefaultCaseStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/DefaultCaseStmt.java    (original)
+++ trunk/src/com/google/caja/parser/js/DefaultCaseStmt.java Wed Jul 15 11:24:34 2009
@@ -28,6 +28,7 @@
   private Statement body;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public DefaultCaseStmt(
       FilePosition pos, Void value, List<? extends Statement> children) {
     this(pos, children.get(0));

Modified: trunk/src/com/google/caja/parser/js/DoWhileLoop.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/DoWhileLoop.java        (original)
+++ trunk/src/com/google/caja/parser/js/DoWhileLoop.java Wed Jul 15 11:24:34 2009
@@ -29,6 +29,7 @@
   private Statement body;
   private Expression condition;

+  @ReflectiveCtor
   public DoWhileLoop(
FilePosition pos, String label, List<? extends ParseTreeNode> children) { this(pos, label, (Statement) children.get(0), (Expression) children.get(1));

Modified: trunk/src/com/google/caja/parser/js/ExpressionStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ExpressionStmt.java     (original)
+++ trunk/src/com/google/caja/parser/js/ExpressionStmt.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private Expression expr;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ExpressionStmt(
       FilePosition pos, Void value, List<? extends Expression> children) {
     this(pos, children.get(0));

Modified: trunk/src/com/google/caja/parser/js/FinallyStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/FinallyStmt.java        (original)
+++ trunk/src/com/google/caja/parser/js/FinallyStmt.java Wed Jul 15 11:24:34 2009
@@ -27,6 +27,7 @@
   private Statement body;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public FinallyStmt(
       FilePosition pos, Void value, List<? extends Statement> children) {
     this(pos, children.get(0));

Modified: trunk/src/com/google/caja/parser/js/ForEachLoop.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ForEachLoop.java        (original)
+++ trunk/src/com/google/caja/parser/js/ForEachLoop.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private Expression container;
   private Statement body;

+  @ReflectiveCtor
   public ForEachLoop(
FilePosition pos, String value, List<? extends ParseTreeNode> children) {
     super(pos, value, ParseTreeNode.class);

Modified: trunk/src/com/google/caja/parser/js/ForLoop.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ForLoop.java    (original)
+++ trunk/src/com/google/caja/parser/js/ForLoop.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private Statement increment;
   private Statement body;

+  @ReflectiveCtor
   public ForLoop(
FilePosition pos, String value, List<? extends ParseTreeNode> children) {
     this(pos, value,

Modified: trunk/src/com/google/caja/parser/js/FormalParam.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/FormalParam.java        (original)
+++ trunk/src/com/google/caja/parser/js/FormalParam.java Wed Jul 15 11:24:34 2009
@@ -25,6 +25,7 @@
  * @author [email protected]
  */
 public final class FormalParam extends Declaration {
+  @ReflectiveCtor
   public FormalParam(
       FilePosition pos, Void value, List<? extends Expression> children) {
     super(pos, value, children);

Modified: trunk/src/com/google/caja/parser/js/FunctionConstructor.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/FunctionConstructor.java        
(original)
+++ trunk/src/com/google/caja/parser/js/FunctionConstructor.java Wed Jul 15 11:24:34 2009
@@ -38,6 +38,7 @@
   private Block body;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public FunctionConstructor(
FilePosition pos, Void value, List<? extends ParseTreeNode> children) {
     super(pos, ParseTreeNode.class);

Modified: trunk/src/com/google/caja/parser/js/FunctionDeclaration.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/FunctionDeclaration.java        
(original)
+++ trunk/src/com/google/caja/parser/js/FunctionDeclaration.java Wed Jul 15 11:24:34 2009
@@ -26,6 +26,7 @@
  * @author [email protected]
  */
 public final class FunctionDeclaration extends Declaration {
+  @ReflectiveCtor
   public FunctionDeclaration(
       FilePosition pos, Void value, List<? extends Expression> children) {
     super(pos, value, children);

Modified: trunk/src/com/google/caja/parser/js/Identifier.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Identifier.java (original)
+++ trunk/src/com/google/caja/parser/js/Identifier.java Wed Jul 15 11:24:34 2009
@@ -37,6 +37,7 @@
 public final class Identifier extends AbstractParseTreeNode {
   private final String name;

+  @ReflectiveCtor
   public Identifier(
FilePosition pos, String name, List<? extends ParseTreeNode> children) {
     this(pos, name);

Modified: trunk/src/com/google/caja/parser/js/IntegerLiteral.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/IntegerLiteral.java     (original)
+++ trunk/src/com/google/caja/parser/js/IntegerLiteral.java Wed Jul 15 11:24:34 2009
@@ -49,6 +49,7 @@
   private final long value;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public IntegerLiteral(
FilePosition pos, Number value, List<? extends ParseTreeNode> children) {
     this(pos, value.longValue());

Modified: trunk/src/com/google/caja/parser/js/LabeledStmtWrapper.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/LabeledStmtWrapper.java (original)
+++ trunk/src/com/google/caja/parser/js/LabeledStmtWrapper.java Wed Jul 15 11:24:34 2009
@@ -36,6 +36,7 @@
   // LabeledStatement.
   private Statement body;

+  @ReflectiveCtor
   public LabeledStmtWrapper(
FilePosition pos, String value, List<? extends ParseTreeNode> children) {
     this(pos, value, (Statement)children.get(0));

Modified: trunk/src/com/google/caja/parser/js/Loop.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Loop.java       (original)
+++ trunk/src/com/google/caja/parser/js/Loop.java       Wed Jul 15 11:24:34 2009
@@ -23,6 +23,7 @@
  * @author [email protected]
  */
 public abstract class Loop extends LabeledStatement {
+  @ReflectiveCtor
   public Loop(
       FilePosition pos, String label,
       Class<? extends ParseTreeNode> childClass) {

Modified: trunk/src/com/google/caja/parser/js/MultiDeclaration.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/MultiDeclaration.java   (original)
+++ trunk/src/com/google/caja/parser/js/MultiDeclaration.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
  */
 public final class MultiDeclaration extends AbstractStatement {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public MultiDeclaration(
       FilePosition pos, Void value, List<? extends Declaration> children) {
     this(pos, children);

Modified: trunk/src/com/google/caja/parser/js/Noop.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Noop.java       (original)
+++ trunk/src/com/google/caja/parser/js/Noop.java       Wed Jul 15 11:24:34 2009
@@ -25,6 +25,7 @@
  */
 public final class Noop extends AbstractStatement {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
public Noop(FilePosition p, Void value, List<? extends Statement> children) {
     super(p, NoChildren.class);
     assert children.isEmpty();

Modified: trunk/src/com/google/caja/parser/js/NullLiteral.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/NullLiteral.java        (original)
+++ trunk/src/com/google/caja/parser/js/NullLiteral.java Wed Jul 15 11:24:34 2009
@@ -29,6 +29,7 @@
    * @param value unused.
    * @param children unused.
    */
+  @ReflectiveCtor
   public NullLiteral(FilePosition pos, NullPlaceholder value,
                      List<? extends ParseTreeNode> children) {
     this(pos);

Modified: trunk/src/com/google/caja/parser/js/ObjectConstructor.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ObjectConstructor.java  (original)
+++ trunk/src/com/google/caja/parser/js/ObjectConstructor.java Wed Jul 15 11:24:34 2009
@@ -35,6 +35,7 @@
  */
 public final class ObjectConstructor extends AbstractExpression {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ObjectConstructor(
       FilePosition pos, Void value, List<? extends Expression> children) {
     super(pos, Expression.class);

Modified: trunk/src/com/google/caja/parser/js/QuotedExpression.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/QuotedExpression.java   (original)
+++ trunk/src/com/google/caja/parser/js/QuotedExpression.java Wed Jul 15 11:24:34 2009
@@ -27,6 +27,7 @@
  */
 public final class QuotedExpression extends AbstractExpression {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public QuotedExpression(
       FilePosition pos, Void value, List<? extends Expression> children) {
     super(pos, Expression.class);

Modified: trunk/src/com/google/caja/parser/js/RealLiteral.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/RealLiteral.java        (original)
+++ trunk/src/com/google/caja/parser/js/RealLiteral.java Wed Jul 15 11:24:34 2009
@@ -30,6 +30,7 @@
   private final double value;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public RealLiteral(
FilePosition pos, Number value, List<? extends ParseTreeNode> children) {
     this(pos, value.doubleValue());

Modified: trunk/src/com/google/caja/parser/js/Reference.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/Reference.java  (original)
+++ trunk/src/com/google/caja/parser/js/Reference.java Wed Jul 15 11:24:34 2009
@@ -31,6 +31,7 @@
   private Identifier identifier;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
public Reference(FilePosition pos, Void value, List<ParseTreeNode> children) {
     super(pos, Identifier.class);
     appendChild(children.get(0));

Modified: trunk/src/com/google/caja/parser/js/RegexpLiteral.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/RegexpLiteral.java      (original)
+++ trunk/src/com/google/caja/parser/js/RegexpLiteral.java Wed Jul 15 11:24:34 2009
@@ -30,6 +30,7 @@
   private final RegexpWrapper value;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public RegexpLiteral(
       FilePosition pos, RegexpWrapper value,
       List<? extends ParseTreeNode> children) {

Modified: trunk/src/com/google/caja/parser/js/ReturnStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ReturnStmt.java (original)
+++ trunk/src/com/google/caja/parser/js/ReturnStmt.java Wed Jul 15 11:24:34 2009
@@ -27,6 +27,7 @@
   private Expression returnValue;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ReturnStmt(
       FilePosition pos, Void value, List<? extends Expression> children) {
     super(pos, Expression.class);

Modified: trunk/src/com/google/caja/parser/js/SimpleOperation.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/SimpleOperation.java    (original)
+++ trunk/src/com/google/caja/parser/js/SimpleOperation.java Wed Jul 15 11:24:34 2009
@@ -24,6 +24,7 @@
  * @author [email protected]
  */
 public final class SimpleOperation extends Operation {
+  @ReflectiveCtor
   public SimpleOperation(
FilePosition pos, Operator value, List<? extends Expression> children) {
     super(pos, value, children);

Modified: trunk/src/com/google/caja/parser/js/SpecialOperation.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/SpecialOperation.java   (original)
+++ trunk/src/com/google/caja/parser/js/SpecialOperation.java Wed Jul 15 11:24:34 2009
@@ -23,6 +23,7 @@
  * @author [email protected]
  */
 public class SpecialOperation extends Operation {
+  @ReflectiveCtor
   public SpecialOperation(
       FilePosition pos, Operator op, List<? extends Expression> operands) {
     super(pos, op, operands);

Modified: trunk/src/com/google/caja/parser/js/StringLiteral.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/StringLiteral.java      (original)
+++ trunk/src/com/google/caja/parser/js/StringLiteral.java Wed Jul 15 11:24:34 2009
@@ -32,6 +32,7 @@
   private final String value;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public StringLiteral(
FilePosition pos, String value, List<? extends ParseTreeNode> children) {
     this(pos, value);

Modified: trunk/src/com/google/caja/parser/js/SwitchStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/SwitchStmt.java (original)
+++ trunk/src/com/google/caja/parser/js/SwitchStmt.java Wed Jul 15 11:24:34 2009
@@ -28,6 +28,7 @@
  * @author [email protected]
  */
 public final class SwitchStmt extends LabeledStatement {
+  @ReflectiveCtor
   public SwitchStmt(
FilePosition pos, String label, List<? extends ParseTreeNode> children) {
     super(pos, label, ParseTreeNode.class);

Modified: trunk/src/com/google/caja/parser/js/ThrowStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/ThrowStmt.java  (original)
+++ trunk/src/com/google/caja/parser/js/ThrowStmt.java Wed Jul 15 11:24:34 2009
@@ -27,6 +27,7 @@
   private Expression exception;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public ThrowStmt(
       FilePosition pos, Void value, List<? extends Expression> children) {
     this(pos, children.get(0));

Modified: trunk/src/com/google/caja/parser/js/TranslatedCode.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/TranslatedCode.java     (original)
+++ trunk/src/com/google/caja/parser/js/TranslatedCode.java Wed Jul 15 11:24:34 2009
@@ -29,6 +29,7 @@
  */
 public final class TranslatedCode extends AbstractStatement {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public TranslatedCode(
       FilePosition pos, Void value, List<? extends Statement> children) {
     super(pos, Statement.class);

Modified: trunk/src/com/google/caja/parser/js/TryStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/TryStmt.java    (original)
+++ trunk/src/com/google/caja/parser/js/TryStmt.java Wed Jul 15 11:24:34 2009
@@ -30,6 +30,7 @@
   private FinallyStmt fin;

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public TryStmt(
       FilePosition pos, Void value, List<? extends Statement> children) {
     super(pos, Statement.class);

Modified: trunk/src/com/google/caja/parser/js/UncajoledModule.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/UncajoledModule.java    (original)
+++ trunk/src/com/google/caja/parser/js/UncajoledModule.java Wed Jul 15 11:24:34 2009
@@ -36,6 +36,7 @@
  */
 public final class UncajoledModule extends AbstractParseTreeNode {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public UncajoledModule(FilePosition pos,
                          Void value,
                          List<? extends Block> children) {

Modified: trunk/src/com/google/caja/parser/js/UseSubset.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/UseSubset.java  (original)
+++ trunk/src/com/google/caja/parser/js/UseSubset.java Wed Jul 15 11:24:34 2009
@@ -36,6 +36,7 @@
   private final String subsetName;

   /** @param children unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public UseSubset(
       FilePosition pos, String subsetName, List<NoChildren> children) {
     this(pos, subsetName);

Modified: trunk/src/com/google/caja/parser/js/UseSubsetDirective.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/UseSubsetDirective.java (original)
+++ trunk/src/com/google/caja/parser/js/UseSubsetDirective.java Wed Jul 15 11:24:34 2009
@@ -77,6 +77,7 @@
  */
 public final class UseSubsetDirective extends AbstractStatement {
   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public UseSubsetDirective(
       FilePosition pos, Void value, List<? extends UseSubset> children) {
     this(pos, children);

Modified: trunk/src/com/google/caja/parser/js/WhileLoop.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/WhileLoop.java  (original)
+++ trunk/src/com/google/caja/parser/js/WhileLoop.java Wed Jul 15 11:24:34 2009
@@ -29,6 +29,7 @@
   private Expression condition;
   private Statement body;

+  @ReflectiveCtor
   public WhileLoop(
FilePosition pos, String label, List<? extends ParseTreeNode> children) { this(pos, label, (Expression) children.get(0), (Statement) children.get(1));

Modified: trunk/src/com/google/caja/parser/js/WithStmt.java
==============================================================================
--- trunk/src/com/google/caja/parser/js/WithStmt.java   (original)
+++ trunk/src/com/google/caja/parser/js/WithStmt.java Wed Jul 15 11:24:34 2009
@@ -33,6 +33,7 @@
     implements NestedScope {

   /** @param value unused.  This ctor is provided for reflection. */
+  @ReflectiveCtor
   public WithStmt(
       FilePosition pos, Void value, List<? extends Statement> children) {
     super(pos, ParseTreeNode.class);

Modified: trunk/tests/com/google/caja/parser/css/CssParserTest.java
==============================================================================
--- trunk/tests/com/google/caja/parser/css/CssParserTest.java   (original)
+++ trunk/tests/com/google/caja/parser/css/CssParserTest.java Wed Jul 15 11:24:34 2009
@@ -174,6 +174,7 @@
         ? MessageLevel.WARNING : MessageLevel.FATAL_ERROR;
     CssTree.StyleSheet stylesheet = new CssParser(
CssParser.makeTokenQueue(cp, mq, false), mq, lvl).parseStyleSheet();
+    assertCloneable(stylesheet);
     StringBuilder sb = new StringBuilder();
     stylesheet.format(new MessageContext(), sb);
     assertEquals(golden.trim(), sb.toString().trim());

Modified: trunk/tests/com/google/caja/parser/js/ParserTest.java
==============================================================================
--- trunk/tests/com/google/caja/parser/js/ParserTest.java       (original)
+++ trunk/tests/com/google/caja/parser/js/ParserTest.java Wed Jul 15 11:24:34 2009
@@ -526,6 +526,7 @@
       String testFile, String goldenFile, String ... errors)
       throws Exception {
     Statement parseTree = js(fromResource(testFile));
+    assertCloneable(parseTree);
     checkFilePositionInvariants(parseTree);

     StringBuilder output = new StringBuilder();

Modified: trunk/tests/com/google/caja/util/CajaTestCase.java
==============================================================================
--- trunk/tests/com/google/caja/util/CajaTestCase.java  (original)
+++ trunk/tests/com/google/caja/util/CajaTestCase.java Wed Jul 15 11:24:34 2009
@@ -240,6 +240,36 @@
     return sb.toString();
   }

+  /**
+ * Ensures that a given node is cloneable by calling {...@code clone()} on it and + * checking sanity of the result. Tests for specific {...@code ParseTreeNode}
+   * subsystems should invoke this on a substantial set of example trees to
+ * guard against problems creeping into the {...@code clone()} implementations.
+   *
+   * @param node a {...@code ParseTreeNode}.
+   */
+  protected void assertCloneable(ParseTreeNode node) {
+    assertDeepEquals(node, node.clone());
+  }
+
+  /**
+   * Ensures that two {...@code ParseTreeNode} trees are deeply equal in the
+ * topology and types of nodes in each tree, and in the {...@code getValue()} and
+   * {...@code getFilePosition()} of each respective node.
+   *
+   * @param a a {...@code ParseTreeNode}.
+   * @param b a {...@code ParseTreeNode}.
+   */
+  protected void assertDeepEquals(ParseTreeNode a, ParseTreeNode b) {
+    assertEquals(a.getValue(), b.getValue());
+    assertEquals(a.getFilePosition(), b.getFilePosition());
+    assertEquals(a.children().size(), b.children().size());
+
+    for (int i = 0; i < a.children().size(); ++i) {
+      assertDeepEquals(a.children().get(i), b.children().get(i));
+    }
+  }
+
   protected void assertMessagesLessSevereThan(MessageLevel level) {
     for (Message msg : mq.getMessages()) {
       if (level.compareTo(msg.getMessageLevel()) <= 0) {

Reply via email to