001    /*
002     * Copyright 2010-2015 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.kotlin.js.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.kotlin.descriptors.VariableDescriptor;
023    import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator;
024    import org.jetbrains.kotlin.js.translate.context.TranslationContext;
025    import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
026    import org.jetbrains.kotlin.psi.KtReferenceExpression;
027    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
028    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
029    import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
030    
031    public class VariableAccessTranslator extends AbstractTranslator implements AccessTranslator {
032        public static VariableAccessTranslator newInstance(
033                @NotNull TranslationContext context,
034                @NotNull KtReferenceExpression referenceExpression,
035                @Nullable JsExpression receiver
036        ) {
037            ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(referenceExpression, context.bindingContext());
038            if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
039                resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall();
040            }
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 AccessTranslator getCached() {
074            JsExpression cachedReceiver = receiver != null ? context().cacheExpressionIfNeeded(receiver) : null;
075            return new CachedVariableAccessTranslator(context(), resolvedCall, cachedReceiver);
076        }
077    
078        private static class CachedVariableAccessTranslator extends VariableAccessTranslator implements AccessTranslator {
079            public CachedVariableAccessTranslator(
080                    @NotNull TranslationContext context,
081                    @NotNull  ResolvedCall<? extends VariableDescriptor> resolvedCall,
082                    @Nullable JsExpression cachedReceiver
083            ) {
084                super(context, resolvedCall, cachedReceiver);
085            }
086    
087            @NotNull
088            @Override
089            public AccessTranslator getCached() {
090                return this;
091            }
092        }
093    }