001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.k2js.translate.reference;
018    
019    import com.google.dart.compiler.backend.js.ast.JsExpression;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
023    import org.jetbrains.jet.lang.psi.JetReferenceExpression;
024    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
025    import org.jetbrains.k2js.translate.callTranslator.CallTranslator;
026    import org.jetbrains.k2js.translate.context.TemporaryVariable;
027    import org.jetbrains.k2js.translate.context.TranslationContext;
028    import org.jetbrains.k2js.translate.general.AbstractTranslator;
029    import org.jetbrains.k2js.translate.utils.BindingUtils;
030    
031    import java.util.Collections;
032    import java.util.List;
033    
034    public class VariableAccessTranslator extends AbstractTranslator implements AccessTranslator {
035        public static VariableAccessTranslator newInstance(
036                @NotNull TranslationContext context,
037                @NotNull JetReferenceExpression referenceExpression,
038                @Nullable JsExpression receiver
039        ) {
040            ResolvedCall<?> resolvedCall = BindingUtils.getResolvedCallForProperty(context.bindingContext(), referenceExpression);
041            assert resolvedCall.getResultingDescriptor() instanceof VariableDescriptor;
042            return new VariableAccessTranslator(context, (ResolvedCall<? extends VariableDescriptor>) resolvedCall, receiver);
043        }
044    
045    
046        private final ResolvedCall<? extends VariableDescriptor> resolvedCall;
047        private final JsExpression receiver;
048    
049        private VariableAccessTranslator(
050                @NotNull TranslationContext context,
051                @NotNull ResolvedCall<? extends VariableDescriptor> resolvedCall,
052                @Nullable JsExpression receiver
053        ) {
054            super(context);
055            this.receiver = receiver;
056            this.resolvedCall = resolvedCall;
057        }
058    
059        @NotNull
060        @Override
061        public JsExpression translateAsGet() {
062            return CallTranslator.instance$.translateGet(context(), resolvedCall, receiver);
063        }
064    
065        @NotNull
066        @Override
067        public JsExpression translateAsSet(@NotNull JsExpression setTo) {
068            return CallTranslator.instance$.translateSet(context(), resolvedCall, setTo, receiver);
069        }
070    
071        @NotNull
072        @Override
073        public CachedAccessTranslator getCached() {
074            TemporaryVariable temporaryVariable = receiver == null ? null : context().declareTemporary(receiver);
075            return new CachedVariableAccessTranslator(context(), resolvedCall, temporaryVariable);
076        }
077    
078        private static class CachedVariableAccessTranslator extends VariableAccessTranslator implements CachedAccessTranslator {
079            @Nullable
080            private final TemporaryVariable cachedReceiver;
081    
082            public CachedVariableAccessTranslator(
083                    @NotNull TranslationContext context,
084                    @NotNull  ResolvedCall<? extends VariableDescriptor> resolvedCall,
085                    @Nullable TemporaryVariable cachedReceiver
086            ) {
087                super(context, resolvedCall, cachedReceiver == null ? null : cachedReceiver.reference());
088                this.cachedReceiver = cachedReceiver;
089            }
090    
091            @NotNull
092            @Override
093            public List<TemporaryVariable> declaredTemporaries() {
094                return cachedReceiver == null ? Collections.<TemporaryVariable>emptyList() : Collections.singletonList(cachedReceiver);
095            }
096    
097            @NotNull
098            @Override
099            public CachedAccessTranslator getCached() {
100                return this;
101            }
102        }
103    
104    }