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