1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 package org.mozilla.javascript.ast; 8 9 import org.mozilla.javascript.Token; 10 11 import java.util.ArrayList; 12 import java.util.Collections; 13 import java.util.List; 14 15 /** 16 * AST node for an Object literal (also called an Object initialiser in 17 * Ecma-262). The elements list will always be non-{@code null}, although 18 * the list will have no elements if the Object literal is empty.<p> 19 * 20 * Node type is {@link Token#OBJECTLIT}.<p> 21 * 22 * <pre><i>ObjectLiteral</i> : 23 * <b>{}</b> 24 * <b>{</b> PropertyNameAndValueList <b>}</b> 25 * <i>PropertyNameAndValueList</i> : 26 * PropertyName <b>:</b> AssignmentExpression 27 * PropertyNameAndValueList , PropertyName <b>:</b> AssignmentExpression 28 * <i>PropertyName</i> : 29 * Identifier 30 * StringLiteral 31 * NumericLiteral</pre> 32 */ 33 public class ObjectLiteral extends AstNode implements DestructuringForm { 34 35 private static final List<ObjectProperty> NO_ELEMS = 36 Collections.unmodifiableList(new ArrayList<ObjectProperty>()); 37 38 private List<ObjectProperty> elements; 39 boolean isDestructuring; 40 41 { 42 type = Token.OBJECTLIT; 43 } 44 ObjectLiteral()45 public ObjectLiteral() { 46 } 47 ObjectLiteral(int pos)48 public ObjectLiteral(int pos) { 49 super(pos); 50 } 51 ObjectLiteral(int pos, int len)52 public ObjectLiteral(int pos, int len) { 53 super(pos, len); 54 } 55 56 /** 57 * Returns the element list. Returns an immutable empty list if there are 58 * no elements. 59 */ getElements()60 public List<ObjectProperty> getElements() { 61 return elements != null ? elements : NO_ELEMS; 62 } 63 64 /** 65 * Sets the element list, and updates the parent of each element. 66 * Replaces any existing elements. 67 * @param elements the element list. Can be {@code null}. 68 */ setElements(List<ObjectProperty> elements)69 public void setElements(List<ObjectProperty> elements) { 70 if (elements == null) { 71 this.elements = null; 72 } else { 73 if (this.elements != null) 74 this.elements.clear(); 75 for (ObjectProperty o : elements) 76 addElement(o); 77 } 78 } 79 80 /** 81 * Adds an element to the list, and sets its parent to this node. 82 * @param element the property node to append to the end of the list 83 * @throws IllegalArgumentException} if element is {@code null} 84 */ addElement(ObjectProperty element)85 public void addElement(ObjectProperty element) { 86 assertNotNull(element); 87 if (elements == null) { 88 elements = new ArrayList<ObjectProperty>(); 89 } 90 elements.add(element); 91 element.setParent(this); 92 } 93 94 /** 95 * Marks this node as being a destructuring form - that is, appearing 96 * in a context such as {@code for ([a, b] in ...)} where it's the 97 * target of a destructuring assignment. 98 */ setIsDestructuring(boolean destructuring)99 public void setIsDestructuring(boolean destructuring) { 100 isDestructuring = destructuring; 101 } 102 103 /** 104 * Returns true if this node is in a destructuring position: 105 * a function parameter, the target of a variable initializer, the 106 * iterator of a for..in loop, etc. 107 */ isDestructuring()108 public boolean isDestructuring() { 109 return isDestructuring; 110 } 111 112 @Override toSource(int depth)113 public String toSource(int depth) { 114 StringBuilder sb = new StringBuilder(); 115 sb.append(makeIndent(depth)); 116 sb.append("{"); 117 if (elements != null) { 118 printList(elements, sb); 119 } 120 sb.append("}"); 121 return sb.toString(); 122 } 123 124 /** 125 * Visits this node, then visits each child property node, in lexical 126 * (source) order. 127 */ 128 @Override visit(NodeVisitor v)129 public void visit(NodeVisitor v) { 130 if (v.visit(this)) { 131 for (ObjectProperty prop : getElements()) { 132 prop.visit(v); 133 } 134 } 135 } 136 } 137