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
017package org.jetbrains.k2js.translate.reference;
018
019import com.google.dart.compiler.backend.js.ast.JsExpression;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.annotations.Nullable;
022import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
023import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
024import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
025import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
026import org.jetbrains.jet.lang.descriptors.impl.PropertyGetterDescriptorImpl;
027import org.jetbrains.jet.lang.resolve.DescriptorResolver;
028import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
029import org.jetbrains.k2js.translate.context.TranslationContext;
030
031/**
032 * For properies /w accessors.
033 */
034public final class KotlinPropertyAccessTranslator extends PropertyAccessTranslator {
035
036    @Nullable
037    private final JsExpression receiver;
038    @NotNull
039    private final PropertyDescriptor propertyDescriptor;
040    @NotNull
041    private final ResolvedCall<?> resolvedCall;
042
043    //TODO: too many params in constructor
044    /*package*/ KotlinPropertyAccessTranslator(@NotNull PropertyDescriptor descriptor,
045                                               @Nullable JsExpression receiver,
046                                               @NotNull ResolvedCall<?> resolvedCall,
047                                               @NotNull TranslationContext context) {
048        super(context);
049        this.receiver = receiver;
050        this.propertyDescriptor = descriptor.getOriginal();
051        this.resolvedCall = resolvedCall;
052    }
053
054    @NotNull
055    @Override
056    public JsExpression translateAsGet() {
057        return translateAsGet(receiver);
058    }
059
060    @Override
061    @NotNull
062    public JsExpression translateAsGet(@Nullable JsExpression receiver) {
063        PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
064        if (getter == null) {
065            //TODO: Temporary hack!!! Rewrite codegen!
066            //Now for consistency we don't create default getter for object declaration property descriptor
067            PropertyGetterDescriptorImpl getterImpl = DescriptorResolver.createDefaultGetter(propertyDescriptor);
068            getterImpl.initialize(propertyDescriptor.getType());
069            ((PropertyDescriptorImpl)propertyDescriptor).initialize(getterImpl, null);
070            getter = getterImpl;
071        }
072        assert getter != null : "Getter for kotlin properties should bot be null.";
073        return callBuilderForAccessor(receiver)
074                .descriptor(getter)
075                .translate();
076    }
077
078    @NotNull
079    @Override
080    public JsExpression translateAsSet(@NotNull JsExpression toSetTo) {
081        return translateAsSet(receiver, toSetTo);
082    }
083
084    @Override
085    @NotNull
086    public JsExpression translateAsSet(@Nullable JsExpression receiver, @NotNull JsExpression toSetTo) {
087        PropertySetterDescriptor setter = propertyDescriptor.getSetter();
088        assert setter != null : "Setter for kotlin properties should not be null.";
089        return callBuilderForAccessor(receiver)
090                .args(toSetTo)
091                .descriptor(setter)
092                .translate();
093    }
094
095    @NotNull
096    private CallBuilder callBuilderForAccessor(@Nullable JsExpression qualifier) {
097        return CallBuilder.build(context())
098                .receiver(qualifier)
099                .resolvedCall(resolvedCall)
100                .type(getCallType());
101    }
102
103
104    @NotNull
105    @Override
106    public CachedAccessTranslator getCached() {
107        return new CachedPropertyAccessTranslator(receiver, this, context());
108    }
109}