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.DeserializedTypeParameterDescriptor;
023    import org.jetbrains.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025    import org.jetbrains.jet.lang.descriptors.impl.*;
026    import org.jetbrains.jet.lang.resolve.DescriptorResolver;
027    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
028    import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
029    import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
030    import org.jetbrains.jet.lang.resolve.name.Name;
031    import org.jetbrains.jet.lang.types.ErrorUtils;
032    import org.jetbrains.jet.lang.types.Variance;
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                case OBJECT_PROPERTY:
131                    return loadProperty(proto);
132                case CONSTRUCTOR:
133                    return loadConstructor(proto);
134            }
135            throw new IllegalArgumentException("Unsupported callable kind: " + callableKind);
136        }
137    
138        @NotNull
139        private PropertyDescriptor loadProperty(@NotNull Callable proto) {
140            PropertyDescriptorImpl property = createPropertyDescriptor(proto);
141    
142            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
143            DescriptorDeserializer local = createChildDeserializer(property, proto.getTypeParameterList(), typeParameters);
144            property.setType(
145                    local.typeDeserializer.type(proto.getReturnType()),
146                    typeParameters,
147                    getExpectedThisObject(),
148                    local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null)
149            );
150    
151            PropertyGetterDescriptorImpl getter = null;
152            PropertySetterDescriptorImpl setter = null;
153    
154            if (Flags.HAS_GETTER.get(proto.getFlags())) {
155                int getterFlags = proto.getGetterFlags();
156                boolean isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags);
157                if (isNotDefault) {
158                    getter = new PropertyGetterDescriptorImpl(
159                            property, getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER),
160                            modality(Flags.MODALITY.get(getterFlags)), visibility(Flags.VISIBILITY.get(getterFlags)),
161                            isNotDefault, !isNotDefault, property.getKind()
162                    );
163                }
164                else {
165                    getter = DescriptorResolver.createDefaultGetter(property);
166                }
167                getter.initialize(property.getReturnType());
168            }
169    
170            if (Flags.HAS_SETTER.get(proto.getFlags())) {
171                int setterFlags = proto.getSetterFlags();
172                boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags);
173                if (isNotDefault) {
174                    setter = new PropertySetterDescriptorImpl(
175                            property, getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER),
176                            modality(Flags.MODALITY.get(setterFlags)), visibility(Flags.VISIBILITY.get(setterFlags)),
177                            isNotDefault, !isNotDefault, property.getKind()
178                    );
179                    setter.initialize(new ValueParameterDescriptorImpl(
180                            setter, 0, Collections.<AnnotationDescriptor>emptyList(),
181                            nameResolver.getName(proto.getSetterParameterName()),
182                            property.getReturnType(), false, null));
183                }
184                else {
185                    setter = DescriptorResolver.createDefaultSetter(property);
186                }
187            }
188    
189            property.initialize(getter, setter);
190    
191            return property;
192        }
193    
194        @NotNull
195        private PropertyDescriptorImpl createPropertyDescriptor(@NotNull Callable proto) {
196            int flags = proto.getFlags();
197            Name name = nameResolver.getName(proto.getName());
198            List<AnnotationDescriptor> annotations = getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY);
199            Visibility visibility = visibility(Flags.VISIBILITY.get(flags));
200            Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(flags);
201    
202            if (callableKind == Callable.CallableKind.OBJECT_PROPERTY) {
203                FqNameUnsafe fqName = DescriptorUtils.getFQName(containingDeclaration).child(name);
204                ClassId objectId = ClassId.fromFqNameAndContainingDeclaration(fqName, (ClassOrNamespaceDescriptor) containingDeclaration);
205                ClassDescriptor objectClass = typeDeserializer.getDescriptorFinder().findClass(objectId);
206                if (objectClass == null) {
207                    // if we are not able to find the class for object property
208                    // then something bad has happened since they should be in the same jar
209                    objectClass = ErrorUtils.createErrorClass(objectId.asSingleFqName().asString());
210                }
211                return new PropertyDescriptorForObjectImpl(containingDeclaration, annotations, visibility, name, objectClass);
212            }
213    
214            return new PropertyDescriptorImpl(
215                    containingDeclaration,
216                    annotations,
217                    modality(Flags.MODALITY.get(flags)),
218                    visibility,
219                    callableKind == Callable.CallableKind.VAR,
220                    name,
221                    memberKind(Flags.MEMBER_KIND.get(flags))
222            );
223        }
224    
225        @NotNull
226        private CallableMemberDescriptor loadFunction(@NotNull Callable proto) {
227            int flags = proto.getFlags();
228            SimpleFunctionDescriptorImpl function = new SimpleFunctionDescriptorImpl(
229                    containingDeclaration,
230                    getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
231                    nameResolver.getName(proto.getName()),
232                    memberKind(Flags.MEMBER_KIND.get(flags))
233            );
234            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
235            DescriptorDeserializer local = createChildDeserializer(function, proto.getTypeParameterList(), typeParameters);
236            function.initialize(
237                    local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
238                    getExpectedThisObject(),
239                    typeParameters,
240                    local.valueParameters(proto.getValueParameterList()),
241                    local.typeDeserializer.type(proto.getReturnType()),
242                    modality(Flags.MODALITY.get(flags)),
243                    visibility(Flags.VISIBILITY.get(flags)),
244                    Flags.INLINE.get(flags)
245    
246            );
247            return function;
248        }
249    
250        @Nullable
251        private ReceiverParameterDescriptor getExpectedThisObject() {
252            return containingDeclaration instanceof ClassDescriptor
253                   ? ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter() : null;
254        }
255    
256        @NotNull
257        private CallableMemberDescriptor loadConstructor(@NotNull Callable proto) {
258            ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
259            ConstructorDescriptorImpl descriptor = new ConstructorDescriptorImpl(
260                    classDescriptor,
261                    getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
262                    // TODO: primary
263                    true);
264            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
265            DescriptorDeserializer local = createChildDeserializer(descriptor, Collections.<TypeParameter>emptyList(), typeParameters);
266            descriptor.initialize(
267                    classDescriptor.getTypeConstructor().getParameters(),
268                    local.valueParameters(proto.getValueParameterList()),
269                    visibility(Flags.VISIBILITY.get(proto.getFlags())),
270                    !classDescriptor.isInner()
271            );
272            descriptor.setReturnType(local.typeDeserializer.type(proto.getReturnType()));
273            return descriptor;
274        }
275    
276        @NotNull
277        private List<AnnotationDescriptor> getAnnotations(@NotNull Callable proto, int flags, @NotNull AnnotatedCallableKind kind) {
278            assert containingDeclaration instanceof ClassOrNamespaceDescriptor
279                    : "Only members in classes or namespaces should be serialized: " + containingDeclaration;
280            return Flags.HAS_ANNOTATIONS.get(flags)
281                   ? annotationDeserializer
282                           .loadCallableAnnotations((ClassOrNamespaceDescriptor) containingDeclaration, proto, nameResolver, kind)
283                   : Collections.<AnnotationDescriptor>emptyList();
284        }
285    
286        private static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) {
287            switch (memberKind) {
288                case DECLARATION:
289                    return CallableMemberDescriptor.Kind.DECLARATION;
290                case FAKE_OVERRIDE:
291                    return CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
292                case DELEGATION:
293                    return CallableMemberDescriptor.Kind.DELEGATION;
294                case SYNTHESIZED:
295                    return CallableMemberDescriptor.Kind.SYNTHESIZED;
296            }
297            throw new IllegalArgumentException("Unknown member kind: " + memberKind);
298        }
299    
300        @NotNull
301        public static Modality modality(@NotNull ProtoBuf.Modality modality) {
302            switch (modality) {
303                case FINAL:
304                    return Modality.FINAL;
305                case OPEN:
306                    return Modality.OPEN;
307                case ABSTRACT:
308                    return Modality.ABSTRACT;
309            }
310            throw new IllegalArgumentException("Unknown modality: " + modality);
311        }
312    
313        @NotNull
314        public static Visibility visibility(@NotNull ProtoBuf.Visibility visibility) {
315            switch (visibility) {
316                case INTERNAL:
317                    return Visibilities.INTERNAL;
318                case PRIVATE:
319                    return Visibilities.PRIVATE;
320                case PROTECTED:
321                    return Visibilities.PROTECTED;
322                case PUBLIC:
323                    return Visibilities.PUBLIC;
324                case EXTRA:
325                    throw new UnsupportedOperationException("Extra visibilities are not supported yet"); // TODO
326            }
327            throw new IllegalArgumentException("Unknown visibility: " + visibility);
328        }
329    
330        @NotNull
331        public static ClassKind classKind(@NotNull ProtoBuf.Class.Kind kind) {
332            switch (kind) {
333                case CLASS:
334                    return ClassKind.CLASS;
335                case TRAIT:
336                    return ClassKind.TRAIT;
337                case ENUM_CLASS:
338                    return ClassKind.ENUM_CLASS;
339                case ENUM_ENTRY:
340                    return ClassKind.ENUM_ENTRY;
341                case ANNOTATION_CLASS:
342                    return ClassKind.ANNOTATION_CLASS;
343                case OBJECT:
344                    return ClassKind.OBJECT;
345                case CLASS_OBJECT:
346                    return ClassKind.CLASS_OBJECT;
347            }
348            throw new IllegalArgumentException("Unknown class kind: " + kind);
349        }
350    
351        @NotNull
352        public List<DeserializedTypeParameterDescriptor> typeParameters(
353                @NotNull List<TypeParameter> protos,
354                @NotNull TypeDeserializer typeDeserializer
355        ) {
356            List<DeserializedTypeParameterDescriptor> result = new ArrayList<DeserializedTypeParameterDescriptor>(protos.size());
357            for (int i = 0; i < protos.size(); i++) {
358                TypeParameter proto = protos.get(i);
359                DeserializedTypeParameterDescriptor descriptor = new DeserializedTypeParameterDescriptor(
360                        storageManager,
361                        typeDeserializer,
362                        proto,
363                        containingDeclaration,
364                        nameResolver.getName(proto.getName()),
365                        variance(proto.getVariance()),
366                        proto.getReified(),
367                        i
368                );
369                result.add(descriptor);
370            }
371            return result;
372        }
373    
374        private static Variance variance(TypeParameter.Variance proto) {
375            switch (proto) {
376                case IN:
377                    return Variance.IN_VARIANCE;
378                case OUT:
379                    return Variance.OUT_VARIANCE;
380                case INV:
381                    return Variance.INVARIANT;
382            }
383            throw new IllegalStateException("Unknown projection: " + proto);
384        }
385    
386        @NotNull
387        private List<ValueParameterDescriptor> valueParameters(@NotNull List<Callable.ValueParameter> protos) {
388            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
389            for (int i = 0; i < protos.size(); i++) {
390                Callable.ValueParameter proto = protos.get(i);
391                result.add(valueParameter(proto, i));
392            }
393            return result;
394        }
395    
396        private ValueParameterDescriptor valueParameter(Callable.ValueParameter proto, int index) {
397            return new ValueParameterDescriptorImpl(
398                    containingDeclaration,
399                    index,
400                    getAnnotations(proto),
401                    nameResolver.getName(proto.getName()),
402                    typeDeserializer.type(proto.getType()),
403                    Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
404                    typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null));
405        }
406    
407        private List<AnnotationDescriptor> getAnnotations(Callable.ValueParameter proto) {
408            return Flags.HAS_ANNOTATIONS.get(proto.getFlags())
409                   ? annotationDeserializer.loadValueParameterAnnotations(proto)
410                   : Collections.<AnnotationDescriptor>emptyList();
411        }
412    }