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