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