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 org.jetbrains.kotlin.js.backend.ast;
006    
007    import org.jetbrains.kotlin.js.common.Symbol;
008    import org.jetbrains.kotlin.js.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(new SmartList<JsVar>(var), false);
038        }
039    
040        public JsVars(JsVar... vars) {
041            this(new SmartList<JsVar>(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 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 void setName(JsName name) {
075                this.name = name;
076            }
077    
078            @Override
079            public Symbol getSymbol() {
080                return name;
081            }
082    
083            public void setInitExpression(JsExpression initExpression) {
084                this.initExpression = initExpression;
085            }
086    
087            @Override
088            public void accept(JsVisitor v) {
089                v.visit(this);
090            }
091    
092            @Override
093            public void acceptChildren(JsVisitor visitor) {
094                if (initExpression != null) {
095                    visitor.accept(initExpression);
096                }
097            }
098    
099            @Override
100            public void traverse(JsVisitorWithContext v, JsContext ctx) {
101                if (v.visit(this, ctx)) {
102                    if (initExpression != null) {
103                        initExpression = v.accept(initExpression);
104                    }
105                }
106                v.endVisit(this, ctx);
107            }
108    
109            @NotNull
110            @Override
111            public JsVar deepCopy() {
112                if (initExpression == null) return new JsVar(name);
113    
114                return new JsVar(name, initExpression.deepCopy()).withMetadataFrom(this);
115            }
116        }
117    
118        public void add(JsVar var) {
119            vars.add(var);
120        }
121    
122        public void addAll(Collection<? extends JsVars.JsVar> vars) {
123            this.vars.addAll(vars);
124        }
125    
126        public void addAll(JsVars otherVars) {
127            this.vars.addAll(otherVars.vars);
128        }
129    
130        public void addIfHasInitializer(JsVar var) {
131            if (var.getInitExpression() != null) {
132                add(var);
133            }
134        }
135    
136        public boolean isEmpty() {
137            return vars.isEmpty();
138        }
139    
140        @Override
141        public Iterator<JsVar> iterator() {
142            return vars.iterator();
143        }
144    
145        public List<JsVar> getVars() {
146            return vars;
147        }
148    
149        @Override
150        public void accept(JsVisitor v) {
151            v.visitVars(this);
152        }
153    
154        @Override
155        public void acceptChildren(JsVisitor visitor) {
156            visitor.acceptWithInsertRemove(vars);
157        }
158    
159        @Override
160        public void traverse(JsVisitorWithContext v, JsContext ctx) {
161            if (v.visit(this, ctx)) {
162                v.acceptList(vars);
163            }
164            v.endVisit(this, ctx);
165        }
166    
167        @NotNull
168        @Override
169        public JsVars deepCopy() {
170            return new JsVars(AstUtil.deepCopy(vars), multiline).withMetadataFrom(this);
171        }
172    }