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.jet.descriptors.serialization;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer;
022    import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
023    import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedTypeParameterDescriptor;
024    import org.jetbrains.jet.lang.descriptors.*;
025    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
026    import org.jetbrains.jet.lang.descriptors.impl.*;
027    import org.jetbrains.jet.lang.resolve.DescriptorFactory;
028    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
029    import org.jetbrains.jet.lang.types.Variance;
030    import org.jetbrains.jet.storage.StorageManager;
031    
032    import java.util.ArrayList;
033    import java.util.Collections;
034    import java.util.List;
035    
036    import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable;
037    import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.TypeParameter;
038    import static org.jetbrains.jet.descriptors.serialization.TypeDeserializer.TypeParameterResolver.NONE;
039    import static org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer.AnnotatedCallableKind;
040    
041    public class DescriptorDeserializer {
042    
043        @NotNull
044        public static DescriptorDeserializer create(
045                @NotNull StorageManager storageManager,
046                @NotNull DeclarationDescriptor containingDeclaration,
047                @NotNull NameResolver nameResolver,
048                @NotNull DescriptorFinder descriptorFinder,
049                @NotNull AnnotationDeserializer annotationDeserializer
050        ) {
051            return new DescriptorDeserializer(storageManager,
052                    new TypeDeserializer(storageManager, null, nameResolver, descriptorFinder,
053                                         "Deserializer for " + containingDeclaration.getName(), NONE),
054                    containingDeclaration, nameResolver, annotationDeserializer);
055        }
056    
057        @NotNull
058        public static DescriptorDeserializer create(
059                @NotNull StorageManager storageManager,
060                @NotNull TypeDeserializer typeDeserializer,
061                @NotNull DeclarationDescriptor containingDeclaration,
062                @NotNull NameResolver nameResolver,
063                @NotNull AnnotationDeserializer annotationDeserializer
064        ) {
065            return new DescriptorDeserializer(storageManager, typeDeserializer, containingDeclaration, nameResolver, annotationDeserializer);
066        }
067    
068        private final DeclarationDescriptor containingDeclaration;
069        private final NameResolver nameResolver;
070        private final TypeDeserializer typeDeserializer;
071        private final AnnotationDeserializer annotationDeserializer;
072    
073        private final StorageManager storageManager;
074    
075        private DescriptorDeserializer(
076                @NotNull StorageManager storageManager,
077                @NotNull TypeDeserializer typeDeserializer,
078                @NotNull DeclarationDescriptor containingDeclaration,
079                @NotNull NameResolver nameResolver,
080                @NotNull AnnotationDeserializer annotationDeserializer
081        ) {
082            this.storageManager = storageManager;
083            this.typeDeserializer = typeDeserializer;
084            this.containingDeclaration = containingDeclaration;
085            this.nameResolver = nameResolver;
086            this.annotationDeserializer = annotationDeserializer;
087        }
088    
089        @NotNull
090        public TypeDeserializer getTypeDeserializer() {
091            return typeDeserializer;
092        }
093    
094        @NotNull
095        public NameResolver getNameResolver() {
096            return nameResolver;
097        }
098    
099        @NotNull
100        public DescriptorDeserializer createChildDeserializer(
101                @NotNull DeclarationDescriptor descriptor,
102                @NotNull final List<TypeParameter> typeParameterProtos,
103                @NotNull final List<TypeParameterDescriptor> typeParameters
104        ) {
105            TypeDeserializer childTypeDeserializer = new TypeDeserializer(
106                    storageManager,
107                    typeDeserializer, "Child deserializer for " + descriptor.getName(),
108                    new TypeDeserializer.TypeParameterResolver() {
109                        @NotNull
110                        @Override
111                        public List<DeserializedTypeParameterDescriptor> getTypeParameters(@NotNull TypeDeserializer typeDeserializer) {
112                            List<DeserializedTypeParameterDescriptor> descriptors = typeParameters(typeParameterProtos, typeDeserializer);
113                            typeParameters.addAll(descriptors);
114                            return descriptors;
115                        }
116                    });
117            return create(storageManager, childTypeDeserializer, descriptor, nameResolver, annotationDeserializer);
118        }
119    
120        @NotNull
121        public CallableMemberDescriptor loadCallable(@NotNull Callable proto) {
122            Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(proto.getFlags());
123            switch (callableKind) {
124                case FUN:
125                    return loadFunction(proto);
126                case VAL:
127                case VAR:
128                    return loadProperty(proto);
129                case CONSTRUCTOR:
130                    return loadConstructor(proto);
131            }
132            throw new IllegalArgumentException("Unsupported callable kind: " + callableKind);
133        }
134    
135        @NotNull
136        private PropertyDescriptor loadProperty(@NotNull Callable proto) {
137            int flags = proto.getFlags();
138    
139            PropertyDescriptorImpl property = new PropertyDescriptorImpl(
140                    containingDeclaration,
141                    getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
142                    modality(Flags.MODALITY.get(flags)),
143                    visibility(Flags.VISIBILITY.get(flags)),
144                    Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
145                    nameResolver.getName(proto.getName()),
146                    memberKind(Flags.MEMBER_KIND.get(flags))
147            );
148    
149            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
150            DescriptorDeserializer local = createChildDeserializer(property, proto.getTypeParameterList(), typeParameters);
151            property.setType(
152                    local.typeDeserializer.type(proto.getReturnType()),
153                    typeParameters,
154                    getExpectedThisObject(),
155                    local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null)
156            );
157    
158            PropertyGetterDescriptorImpl getter = null;
159            PropertySetterDescriptorImpl setter = null;
160    
161            if (Flags.HAS_GETTER.get(flags)) {
162                int getterFlags = proto.getGetterFlags();
163                boolean isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags);
164                if (isNotDefault) {
165                    getter = new PropertyGetterDescriptorImpl(
166                            property, getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER),
167                            modality(Flags.MODALITY.get(getterFlags)), visibility(Flags.VISIBILITY.get(getterFlags)),
168                            isNotDefault, !isNotDefault, property.getKind()
169                    );
170                }
171                else {
172                    getter = DescriptorFactory.createDefaultGetter(property);
173                }
174                getter.initialize(property.getReturnType());
175            }
176    
177            if (Flags.HAS_SETTER.get(flags)) {
178                int setterFlags = proto.getSetterFlags();
179                boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags);
180                if (isNotDefault) {
181                    setter = new PropertySetterDescriptorImpl(
182                            property, getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER),
183                            modality(Flags.MODALITY.get(setterFlags)), visibility(Flags.VISIBILITY.get(setterFlags)),
184                            isNotDefault, !isNotDefault, property.getKind()
185                    );
186                    DescriptorDeserializer setterLocal = local.createChildDeserializer(setter, Collections.<TypeParameter>emptyList(),
187                                                                                       Collections.<TypeParameterDescriptor>emptyList());
188                    List<ValueParameterDescriptor> valueParameters = setterLocal.valueParameters(proto, AnnotatedCallableKind.PROPERTY_SETTER);
189                    assert valueParameters.size() == 1 : "Property setter should have a single value parameter: " + setter;
190                    setter.initialize(valueParameters.get(0));
191                }
192                else {
193                    setter = DescriptorFactory.createDefaultSetter(property);
194                }
195            }
196    
197            property.initialize(getter, setter);
198    
199            return property;
200        }
201    
202        @NotNull
203        private CallableMemberDescriptor loadFunction(@NotNull Callable proto) {
204            int flags = proto.getFlags();
205            DeserializedSimpleFunctionDescriptor function = new DeserializedSimpleFunctionDescriptor(
206                    containingDeclaration, proto,
207                    annotationDeserializer,
208                    nameResolver
209            );
210            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
211            DescriptorDeserializer local = createChildDeserializer(function, proto.getTypeParameterList(), typeParameters);
212            function.initialize(
213                    local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
214                    getExpectedThisObject(),
215                    typeParameters,
216                    local.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
217                    local.typeDeserializer.type(proto.getReturnType()),
218                    modality(Flags.MODALITY.get(flags)),
219                    visibility(Flags.VISIBILITY.get(flags))
220            );
221            return function;
222        }
223    
224        @Nullable
225        private ReceiverParameterDescriptor getExpectedThisObject() {
226            return containingDeclaration instanceof ClassDescriptor
227                   ? ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter() : null;
228        }
229    
230        @NotNull
231        private CallableMemberDescriptor loadConstructor(@NotNull Callable proto) {
232            ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
233            ConstructorDescriptorImpl descriptor = new ConstructorDescriptorImpl(
234                    classDescriptor,
235                    getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
236                    // TODO: primary
237                    true);
238            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
239            DescriptorDeserializer local = createChildDeserializer(descriptor, Collections.<TypeParameter>emptyList(), typeParameters);
240            descriptor.initialize(
241                    classDescriptor.getTypeConstructor().getParameters(),
242                    local.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
243                    visibility(Flags.VISIBILITY.get(proto.getFlags())),
244                    DescriptorUtils.isConstructorOfStaticNestedClass(descriptor)
245            );
246            descriptor.setReturnType(local.typeDeserializer.type(proto.getReturnType()));
247            return descriptor;
248        }
249    
250        @NotNull
251        private List<AnnotationDescriptor> getAnnotations(@NotNull Callable proto, int flags, @NotNull AnnotatedCallableKind kind) {
252            return getAnnotations(containingDeclaration, proto, flags, kind, annotationDeserializer, nameResolver);
253        }
254    
255        public static List<AnnotationDescriptor> getAnnotations(
256                @NotNull DeclarationDescriptor containingDeclaration,
257                @NotNull Callable proto,
258                int flags,
259                @NotNull AnnotatedCallableKind kind,
260                @NotNull AnnotationDeserializer annotationDeserializer,
261                @NotNull NameResolver nameResolver
262        ) {
263            assert containingDeclaration instanceof ClassOrNamespaceDescriptor
264                    : "Only members in classes or namespaces should be serialized: " + containingDeclaration;
265            return Flags.HAS_ANNOTATIONS.get(flags)
266                   ? annotationDeserializer
267                           .loadCallableAnnotations((ClassOrNamespaceDescriptor) containingDeclaration, proto, nameResolver, kind)
268                   : Collections.<AnnotationDescriptor>emptyList();
269        }
270    
271        public static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) {
272            switch (memberKind) {
273                case DECLARATION:
274                    return CallableMemberDescriptor.Kind.DECLARATION;
275                case FAKE_OVERRIDE:
276                    return CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
277                case DELEGATION:
278                    return CallableMemberDescriptor.Kind.DELEGATION;
279                case SYNTHESIZED:
280                    return CallableMemberDescriptor.Kind.SYNTHESIZED;
281            }
282            throw new IllegalArgumentException("Unknown member kind: " + memberKind);
283        }
284    
285        @NotNull
286        public static Modality modality(@NotNull ProtoBuf.Modality modality) {
287            switch (modality) {
288                case FINAL:
289                    return Modality.FINAL;
290                case OPEN:
291                    return Modality.OPEN;
292                case ABSTRACT:
293                    return Modality.ABSTRACT;
294            }
295            throw new IllegalArgumentException("Unknown modality: " + modality);
296        }
297    
298        @NotNull
299        public static Visibility visibility(@NotNull ProtoBuf.Visibility visibility) {
300            switch (visibility) {
301                case INTERNAL:
302                    return Visibilities.INTERNAL;
303                case PRIVATE:
304                    return Visibilities.PRIVATE;
305                case PROTECTED:
306                    return Visibilities.PROTECTED;
307                case PUBLIC:
308                    return Visibilities.PUBLIC;
309                case EXTRA:
310                    throw new UnsupportedOperationException("Extra visibilities are not supported yet"); // TODO
311            }
312            throw new IllegalArgumentException("Unknown visibility: " + visibility);
313        }
314    
315        @NotNull
316        public static ClassKind classKind(@NotNull ProtoBuf.Class.Kind kind) {
317            switch (kind) {
318                case CLASS:
319                    return ClassKind.CLASS;
320                case TRAIT:
321                    return ClassKind.TRAIT;
322                case ENUM_CLASS:
323                    return ClassKind.ENUM_CLASS;
324                case ENUM_ENTRY:
325                    return ClassKind.ENUM_ENTRY;
326                case ANNOTATION_CLASS:
327                    return ClassKind.ANNOTATION_CLASS;
328                case OBJECT:
329                    return ClassKind.OBJECT;
330                case CLASS_OBJECT:
331                    return ClassKind.CLASS_OBJECT;
332            }
333            throw new IllegalArgumentException("Unknown class kind: " + kind);
334        }
335    
336        @NotNull
337        public List<DeserializedTypeParameterDescriptor> typeParameters(
338                @NotNull List<TypeParameter> protos,
339                @NotNull TypeDeserializer typeDeserializer
340        ) {
341            List<DeserializedTypeParameterDescriptor> result = new ArrayList<DeserializedTypeParameterDescriptor>(protos.size());
342            for (int i = 0; i < protos.size(); i++) {
343                TypeParameter proto = protos.get(i);
344                DeserializedTypeParameterDescriptor descriptor = new DeserializedTypeParameterDescriptor(
345                        storageManager,
346                        typeDeserializer,
347                        proto,
348                        containingDeclaration,
349                        nameResolver.getName(proto.getName()),
350                        variance(proto.getVariance()),
351                        proto.getReified(),
352                        i
353                );
354                result.add(descriptor);
355            }
356            return result;
357        }
358    
359        private static Variance variance(TypeParameter.Variance proto) {
360            switch (proto) {
361                case IN:
362                    return Variance.IN_VARIANCE;
363                case OUT:
364                    return Variance.OUT_VARIANCE;
365                case INV:
366                    return Variance.INVARIANT;
367            }
368            throw new IllegalStateException("Unknown projection: " + proto);
369        }
370    
371        @NotNull
372        private List<ValueParameterDescriptor> valueParameters(@NotNull Callable callable, @NotNull AnnotatedCallableKind kind) {
373            DeclarationDescriptor containerOfCallable = containingDeclaration.getContainingDeclaration();
374            assert containerOfCallable instanceof ClassOrNamespaceDescriptor
375                    : "Only members in classes or namespaces should be serialized: " + containerOfCallable;
376            ClassOrNamespaceDescriptor classOrNamespace = (ClassOrNamespaceDescriptor) containerOfCallable;
377    
378            List<Callable.ValueParameter> protos = callable.getValueParameterList();
379            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
380            for (int i = 0; i < protos.size(); i++) {
381                Callable.ValueParameter proto = protos.get(i);
382                result.add(new ValueParameterDescriptorImpl(
383                        containingDeclaration,
384                        i,
385                        getAnnotations(classOrNamespace, callable, kind, proto),
386                        nameResolver.getName(proto.getName()),
387                        typeDeserializer.type(proto.getType()),
388                        Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
389                        typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null))
390                );
391            }
392            return result;
393        }
394    
395        @NotNull
396        private List<AnnotationDescriptor> getAnnotations(
397                @NotNull ClassOrNamespaceDescriptor classOrNamespace,
398                @NotNull Callable callable,
399                @NotNull AnnotatedCallableKind kind,
400                @NotNull Callable.ValueParameter valueParameter
401        ) {
402            return Flags.HAS_ANNOTATIONS.get(valueParameter.getFlags())
403                   ? annotationDeserializer.loadValueParameterAnnotations(classOrNamespace, callable, nameResolver, kind, valueParameter)
404                   : Collections.<AnnotationDescriptor>emptyList();
405        }
406    }