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.codegen;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.descriptors.*;
022    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
023    import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
024    import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl;
025    import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl;
026    import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
027    import org.jetbrains.kotlin.name.Name;
028    import org.jetbrains.kotlin.resolve.DescriptorUtils;
029    import org.jetbrains.kotlin.types.KotlinType;
030    
031    import java.util.Collections;
032    
033    public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl implements AccessorForCallableDescriptor<PropertyDescriptor> {
034        private final PropertyDescriptor calleeDescriptor;
035        private final ClassDescriptor superCallTarget;
036        private final String nameSuffix;
037        private final boolean withSyntheticGetterAccessor;
038        private final boolean withSyntheticSetterAccessor;
039    
040        public AccessorForPropertyDescriptor(
041                @NotNull PropertyDescriptor property,
042                @NotNull DeclarationDescriptor containingDeclaration,
043                @Nullable ClassDescriptor superCallTarget,
044                @NotNull String nameSuffix,
045                boolean getterAccessorRequired,
046                boolean setterAccessorRequired
047        ) {
048            this(property, property.getType(), DescriptorUtils.getReceiverParameterType(property.getExtensionReceiverParameter()),
049                 property.getDispatchReceiverParameter(), containingDeclaration, superCallTarget, nameSuffix,
050                 getterAccessorRequired, setterAccessorRequired);
051        }
052    
053        protected AccessorForPropertyDescriptor(
054                @NotNull PropertyDescriptor original,
055                @NotNull KotlinType propertyType,
056                @Nullable KotlinType receiverType,
057                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
058                @NotNull DeclarationDescriptor containingDeclaration,
059                @Nullable ClassDescriptor superCallTarget,
060                @NotNull String nameSuffix
061        ) {
062            this(original, propertyType, receiverType, dispatchReceiverParameter, containingDeclaration, superCallTarget, nameSuffix, true, true);
063        }
064    
065        protected AccessorForPropertyDescriptor(
066                @NotNull PropertyDescriptor original,
067                @NotNull KotlinType propertyType,
068                @Nullable KotlinType receiverType,
069                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
070                @NotNull DeclarationDescriptor containingDeclaration,
071                @Nullable ClassDescriptor superCallTarget,
072                @NotNull String nameSuffix,
073                boolean getterAccessorRequired,
074                boolean setterAccessorRequired
075        ) {
076            super(containingDeclaration, null, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
077                  original.isVar(), Name.identifier("access$" + nameSuffix),
078                  Kind.DECLARATION, SourceElement.NO_SOURCE, /* lateInit = */ false, /* isConst = */ false);
079    
080            this.calleeDescriptor = original;
081            this.superCallTarget = superCallTarget;
082            this.nameSuffix = nameSuffix;
083            setType(propertyType, Collections.<TypeParameterDescriptorImpl>emptyList(), dispatchReceiverParameter, receiverType);
084    
085            this.withSyntheticGetterAccessor = getterAccessorRequired;
086            this.withSyntheticSetterAccessor = setterAccessorRequired;
087    
088            PropertyGetterDescriptorImpl getterDescriptor =
089                    getterAccessorRequired ? new Getter(this) : (PropertyGetterDescriptorImpl) original.getGetter();
090            PropertySetterDescriptor setterDescriptor =
091                    setterAccessorRequired ? new Setter(this) : original.getSetter();
092            initialize(getterDescriptor, setterDescriptor);
093        }
094    
095        public static class Getter extends PropertyGetterDescriptorImpl implements AccessorForCallableDescriptor<PropertyGetterDescriptor> {
096            public Getter(AccessorForPropertyDescriptor property) {
097                super(property, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
098                      /* isDefault = */ false, /* isExternal = */ false, Kind.DECLARATION, null, SourceElement.NO_SOURCE);
099                initialize(property.getType());
100            }
101    
102            @NotNull
103            @Override
104            public PropertyGetterDescriptor getCalleeDescriptor() {
105                //noinspection ConstantConditions
106                return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getGetter();
107            }
108    
109            @Override
110            @Nullable
111            public ClassDescriptor getSuperCallTarget() {
112                return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallTarget();
113            }
114    
115        }
116    
117        public static class Setter extends PropertySetterDescriptorImpl implements AccessorForCallableDescriptor<PropertySetterDescriptor>{
118            public Setter(AccessorForPropertyDescriptor property) {
119                super(property, Annotations.Companion.getEMPTY(), Modality.FINAL, Visibilities.LOCAL,
120                      /* isDefault = */ false, /* isExternal = */ false, Kind.DECLARATION, null, SourceElement.NO_SOURCE);
121                initializeDefault();
122            }
123    
124            @NotNull
125            @Override
126            public PropertySetterDescriptor getCalleeDescriptor() {
127                //noinspection ConstantConditions
128                return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getCalleeDescriptor().getSetter();
129            }
130    
131            @Override
132            @Nullable
133            public ClassDescriptor getSuperCallTarget() {
134                return ((AccessorForPropertyDescriptor) getCorrespondingProperty()).getSuperCallTarget();
135            }
136        }
137    
138        @NotNull
139        @Override
140        public PropertyDescriptor getCalleeDescriptor() {
141            return calleeDescriptor;
142        }
143    
144        @Override
145        public ClassDescriptor getSuperCallTarget() {
146            return superCallTarget;
147        }
148    
149        @NotNull
150        public String getAccessorSuffix() {
151            return nameSuffix;
152        }
153    
154        public boolean isWithSyntheticGetterAccessor() {
155            return withSyntheticGetterAccessor;
156        }
157    
158        public boolean isWithSyntheticSetterAccessor() {
159            return withSyntheticSetterAccessor;
160        }
161    }