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 org.jetbrains.annotations.NotNull;
010    
011    /**
012     * Represents a JavaScript expression that references a name.
013     */
014    public final class JsNameRef extends JsExpressionImpl implements HasName {
015        private String ident;
016        private JsName name;
017        private JsExpression qualifier;
018    
019        public JsNameRef(@NotNull JsName name) {
020            this.name = name;
021        }
022    
023        public JsNameRef(@NotNull String ident) {
024            this.ident = ident;
025        }
026    
027        public JsNameRef(@NotNull String ident, JsExpression qualifier) {
028            this.ident = ident;
029            this.qualifier = qualifier;
030        }
031    
032        public JsNameRef(@NotNull String ident, @NotNull String qualifier) {
033            this(ident, new JsNameRef(qualifier));
034        }
035    
036        public JsNameRef(@NotNull JsName name, JsExpression qualifier) {
037            this.name = name;
038            this.qualifier = qualifier;
039        }
040    
041        @NotNull
042        public String getIdent() {
043            return (name == null) ? ident : name.getIdent();
044        }
045    
046        @Override
047        public JsName getName() {
048            return name;
049        }
050    
051        @Override
052        public Symbol getSymbol() {
053            return name;
054        }
055    
056        public JsExpression getQualifier() {
057            return qualifier;
058        }
059    
060        @Override
061        public boolean isLeaf() {
062            return qualifier == null;
063        }
064    
065        public void resolve(JsName name) {
066            this.name = name;
067            ident = null;
068        }
069    
070        public void setQualifier(JsExpression qualifier) {
071            this.qualifier = qualifier;
072        }
073    
074        @Override
075        public void accept(JsVisitor v) {
076            v.visitNameRef(this);
077        }
078    
079        @Override
080        public void acceptChildren(JsVisitor visitor) {
081            if (qualifier != null) {
082               visitor.accept(qualifier);
083            }
084        }
085    
086        @Override
087        public void traverse(JsVisitorWithContext v, JsContext ctx) {
088            if (v.visit(this, ctx)) {
089                if (qualifier != null) {
090                    qualifier = v.accept(qualifier);
091                }
092            }
093            v.endVisit(this, ctx);
094        }
095    
096        @NotNull
097        @Override
098        public JsNameRef deepCopy() {
099            JsExpression qualifierCopy = AstUtil.deepCopy(qualifier);
100    
101            if (name != null) return new JsNameRef(name, qualifierCopy);
102    
103            return new JsNameRef(ident, qualifierCopy).withMetadataFrom(this);
104        }
105    }