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