001    // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
002    // for details. All rights reserved. Use of this source code is governed by a
003    // BSD-style license that can be found in the LICENSE file.
004    
005    package com.google.dart.compiler.backend.js.ast;
006    
007    import com.google.dart.compiler.common.Symbol;
008    import com.google.dart.compiler.util.AstUtil;
009    import com.intellij.util.SmartList;
010    import org.jetbrains.annotations.NotNull;
011    import org.jetbrains.annotations.Nullable;
012    
013    import java.util.*;
014    
015    /**
016     * A JavaScript <code>var</code> statement.
017     */
018    public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterable<JsVars.JsVar> {
019        private final List<JsVar> vars;
020    
021        private final boolean multiline;
022    
023        public JsVars() {
024            this(new SmartList<JsVar>(), false);
025        }
026    
027        public JsVars(boolean multiline) {
028            this(new SmartList<JsVar>(), multiline);
029        }
030    
031        public JsVars(List<JsVar> vars, boolean multiline) {
032            this.vars = vars;
033            this.multiline = multiline;
034        }
035    
036        public JsVars(JsVar var) {
037            this(Collections.singletonList(var), false);
038        }
039    
040        public JsVars(JsVar... vars) {
041            this(Arrays.asList(vars), false);
042        }
043    
044        public boolean isMultiline() {
045            return multiline;
046        }
047    
048        /**
049         * A var declared using the JavaScript <code>var</code> statement.
050         */
051        public static class JsVar extends SourceInfoAwareJsNode implements HasName {
052            private final JsName name;
053            private JsExpression initExpression;
054    
055            public JsVar(JsName name) {
056                this.name = name;
057            }
058    
059            public JsVar(JsName name, @Nullable JsExpression initExpression) {
060                this.name = name;
061                this.initExpression = initExpression;
062            }
063    
064            public JsExpression getInitExpression() {
065                return initExpression;
066            }
067    
068            @Override
069            public JsName getName() {
070                return name;
071            }
072    
073            @Override
074            public Symbol getSymbol() {
075                return name;
076            }
077    
078            public void setInitExpression(JsExpression initExpression) {
079                this.initExpression = initExpression;
080            }
081    
082            @Override
083            public void accept(JsVisitor v) {
084                v.visit(this);
085            }
086    
087            @Override
088            public void acceptChildren(JsVisitor visitor) {
089                if (initExpression != null) {
090                    visitor.accept(initExpression);
091                }
092            }
093    
094            @Override
095            public void traverse(JsVisitorWithContext v, JsContext ctx) {
096                if (v.visit(this, ctx)) {
097                    if (initExpression != null) {
098                        initExpression = v.accept(initExpression);
099                    }
100                }
101                v.endVisit(this, ctx);
102            }
103    
104            @NotNull
105            @Override
106            public JsVar deepCopy() {
107                if (initExpression == null) return new JsVar(name);
108    
109                return new JsVar(name, initExpression.deepCopy()).withMetadataFrom(this);
110            }
111        }
112    
113        public void add(JsVar var) {
114            vars.add(var);
115        }
116    
117        public void addAll(Collection<? extends JsVars.JsVar> vars) {
118            this.vars.addAll(vars);
119        }
120    
121        public void addAll(JsVars otherVars) {
122            this.vars.addAll(otherVars.vars);
123        }
124    
125        public void addIfHasInitializer(JsVar var) {
126            if (var.getInitExpression() != null) {
127                add(var);
128            }
129        }
130    
131        public boolean isEmpty() {
132            return vars.isEmpty();
133        }
134    
135        @Override
136        public Iterator<JsVar> iterator() {
137            return vars.iterator();
138        }
139    
140        public List<JsVar> getVars() {
141            return vars;
142        }
143    
144        @Override
145        public void accept(JsVisitor v) {
146            v.visitVars(this);
147        }
148    
149        @Override
150        public void acceptChildren(JsVisitor visitor) {
151            visitor.acceptWithInsertRemove(vars);
152        }
153    
154        @Override
155        public void traverse(JsVisitorWithContext v, JsContext ctx) {
156            if (v.visit(this, ctx)) {
157                v.acceptList(vars);
158            }
159            v.endVisit(this, ctx);
160        }
161    
162        @NotNull
163        @Override
164        public JsVars deepCopy() {
165            return new JsVars(AstUtil.deepCopy(vars), multiline).withMetadataFrom(this);
166        }
167    }