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 kotlin.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.descriptors.serialization.descriptors.*;
023    import org.jetbrains.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
025    import org.jetbrains.jet.lang.descriptors.impl.*;
026    import org.jetbrains.jet.lang.resolve.DescriptorFactory;
027    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
028    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
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.Deserializers.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 Deserializers deserializers
050        ) {
051            return new DescriptorDeserializer(storageManager,
052                    new TypeDeserializer(storageManager, null, nameResolver, descriptorFinder,
053                                         "Deserializer for " + containingDeclaration.getName(), NONE),
054                    containingDeclaration, nameResolver, deserializers);
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 Deserializers deserializers
064        ) {
065            return new DescriptorDeserializer(storageManager, typeDeserializer, containingDeclaration, nameResolver, deserializers);
066        }
067    
068        private final DeclarationDescriptor containingDeclaration;
069        private final NameResolver nameResolver;
070        private final TypeDeserializer typeDeserializer;
071        private final Deserializers deserializers;
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 Deserializers deserializers
081        ) {
082            this.storageManager = storageManager;
083            this.typeDeserializer = typeDeserializer;
084            this.containingDeclaration = containingDeclaration;
085            this.nameResolver = nameResolver;
086            this.deserializers = deserializers;
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, deserializers);
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 final Callable proto) {
137            final int flags = proto.getFlags();
138    
139            DeserializedPropertyDescriptor property = new DeserializedPropertyDescriptor(
140                    containingDeclaration,
141                    null,
142                    getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
143                    modality(Flags.MODALITY.get(flags)),
144                    visibility(Flags.VISIBILITY.get(flags)),
145                    Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
146                    nameResolver.getName(proto.getName()),
147                    memberKind(Flags.MEMBER_KIND.get(flags)),
148                    proto,
149                    nameResolver
150            );
151    
152            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
153            DescriptorDeserializer local = createChildDeserializer(property, proto.getTypeParameterList(), typeParameters);
154            property.setType(
155                    local.typeDeserializer.type(proto.getReturnType()),
156                    typeParameters,
157                    getExpectedThisObject(),
158                    local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null)
159            );
160    
161            PropertyGetterDescriptorImpl getter = null;
162            PropertySetterDescriptorImpl setter = null;
163    
164            if (Flags.HAS_GETTER.get(flags)) {
165                int getterFlags = proto.getGetterFlags();
166                boolean isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags);
167                if (isNotDefault) {
168                    getter = new PropertyGetterDescriptorImpl(property,
169                                                              getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER),
170                                                              modality(Flags.MODALITY.get(getterFlags)),
171                                                              visibility(Flags.VISIBILITY.get(getterFlags)), isNotDefault, !isNotDefault,
172                                                              property.getKind(), null);
173                }
174                else {
175                    getter = DescriptorFactory.createDefaultGetter(property);
176                }
177                getter.initialize(property.getReturnType());
178            }
179    
180            if (Flags.HAS_SETTER.get(flags)) {
181                int setterFlags = proto.getSetterFlags();
182                boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags);
183                if (isNotDefault) {
184                    setter = new PropertySetterDescriptorImpl(property,
185                                                              getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER),
186                                                              modality(Flags.MODALITY.get(setterFlags)),
187                                                              visibility(Flags.VISIBILITY.get(setterFlags)), isNotDefault, !isNotDefault,
188                                                              property.getKind(), null);
189                    DescriptorDeserializer setterLocal = local.createChildDeserializer(setter, Collections.<TypeParameter>emptyList(),
190                                                                                       Collections.<TypeParameterDescriptor>emptyList());
191                    List<ValueParameterDescriptor> valueParameters = setterLocal.valueParameters(proto, AnnotatedCallableKind.PROPERTY_SETTER);
192                    assert valueParameters.size() == 1 : "Property setter should have a single value parameter: " + setter;
193                    setter.initialize(valueParameters.get(0));
194                }
195                else {
196                    setter = DescriptorFactory.createDefaultSetter(property);
197                }
198            }
199    
200            if (Flags.HAS_CONSTANT.get(flags)) {
201                property.setCompileTimeInitializer(
202                        storageManager.createNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
203                            @Nullable
204                            @Override
205                            public CompileTimeConstant<?> invoke() {
206                                assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
207                                        : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
208                                return deserializers.getConstantDeserializer().loadPropertyConstant(
209                                                                (ClassOrPackageFragmentDescriptor) containingDeclaration,
210                                                                proto, nameResolver,
211                                                                AnnotatedCallableKind.PROPERTY);
212                            }
213                        })
214                );
215            }
216    
217            property.initialize(getter, setter);
218    
219            return property;
220        }
221    
222        @NotNull
223        private CallableMemberDescriptor loadFunction(@NotNull Callable proto) {
224            int flags = proto.getFlags();
225            DeserializedSimpleFunctionDescriptor function = DeserializedSimpleFunctionDescriptor.create(
226                    containingDeclaration, proto,
227                    deserializers,
228                    nameResolver
229            );
230            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
231            DescriptorDeserializer local = createChildDeserializer(function, proto.getTypeParameterList(), typeParameters);
232            function.initialize(
233                    local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
234                    getExpectedThisObject(),
235                    typeParameters,
236                    local.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
237                    local.typeDeserializer.type(proto.getReturnType()),
238                    modality(Flags.MODALITY.get(flags)),
239                    visibility(Flags.VISIBILITY.get(flags))
240            );
241            return function;
242        }
243    
244        @Nullable
245        private ReceiverParameterDescriptor getExpectedThisObject() {
246            return containingDeclaration instanceof ClassDescriptor
247                   ? ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter() : null;
248        }
249    
250        @NotNull
251        private CallableMemberDescriptor loadConstructor(@NotNull Callable proto) {
252            ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
253            ConstructorDescriptorImpl descriptor = ConstructorDescriptorImpl.create(
254                    classDescriptor,
255                    getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
256                    // TODO: primary
257                    true);
258            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
259            DescriptorDeserializer local = createChildDeserializer(descriptor, Collections.<TypeParameter>emptyList(), typeParameters);
260            descriptor.initialize(
261                    classDescriptor.getTypeConstructor().getParameters(),
262                    local.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
263                    visibility(Flags.VISIBILITY.get(proto.getFlags())),
264                    DescriptorUtils.isConstructorOfStaticNestedClass(descriptor)
265            );
266            descriptor.setReturnType(local.typeDeserializer.type(proto.getReturnType()));
267            return descriptor;
268        }
269    
270        @NotNull
271        private Annotations getAnnotations(@NotNull Callable proto, int flags, @NotNull AnnotatedCallableKind kind) {
272            return getAnnotations(containingDeclaration, proto, flags, kind, deserializers.getAnnotationDeserializer(), nameResolver);
273        }
274    
275        public static Annotations getAnnotations(
276                @NotNull DeclarationDescriptor containingDeclaration,
277                @NotNull Callable proto,
278                int flags,
279                @NotNull AnnotatedCallableKind kind,
280                @NotNull AnnotationDeserializer annotationDeserializer,
281                @NotNull NameResolver nameResolver
282        ) {
283            assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
284                    : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
285            return Flags.HAS_ANNOTATIONS.get(flags)
286                   ? annotationDeserializer
287                           .loadCallableAnnotations((ClassOrPackageFragmentDescriptor) containingDeclaration, proto, nameResolver, kind)
288                   : Annotations.EMPTY;
289        }
290    
291        public static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) {
292            switch (memberKind) {
293                case DECLARATION:
294                    return CallableMemberDescriptor.Kind.DECLARATION;
295                case FAKE_OVERRIDE:
296                    return CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
297                case DELEGATION:
298                    return CallableMemberDescriptor.Kind.DELEGATION;
299                case SYNTHESIZED:
300                    return CallableMemberDescriptor.Kind.SYNTHESIZED;
301            }
302            throw new IllegalArgumentException("Unknown member kind: " + memberKind);
303        }
304    
305        @NotNull
306        public static Modality modality(@NotNull ProtoBuf.Modality modality) {
307            switch (modality) {
308                case FINAL:
309                    return Modality.FINAL;
310                case OPEN:
311                    return Modality.OPEN;
312                case ABSTRACT:
313                    return Modality.ABSTRACT;
314            }
315            throw new IllegalArgumentException("Unknown modality: " + modality);
316        }
317    
318        @NotNull
319        public static Visibility visibility(@NotNull ProtoBuf.Visibility visibility) {
320            switch (visibility) {
321                case INTERNAL:
322                    return Visibilities.INTERNAL;
323                case PRIVATE:
324                    return Visibilities.PRIVATE;
325                case PROTECTED:
326                    return Visibilities.PROTECTED;
327                case PUBLIC:
328                    return Visibilities.PUBLIC;
329                case EXTRA:
330                    throw new UnsupportedOperationException("Extra visibilities are not supported yet"); // TODO
331            }
332            throw new IllegalArgumentException("Unknown visibility: " + visibility);
333        }
334    
335        @NotNull
336        public static ClassKind classKind(@NotNull ProtoBuf.Class.Kind kind) {
337            switch (kind) {
338                case CLASS:
339                    return ClassKind.CLASS;
340                case TRAIT:
341                    return ClassKind.TRAIT;
342                case ENUM_CLASS:
343                    return ClassKind.ENUM_CLASS;
344                case ENUM_ENTRY:
345                    return ClassKind.ENUM_ENTRY;
346                case ANNOTATION_CLASS:
347                    return ClassKind.ANNOTATION_CLASS;
348                case OBJECT:
349                    return ClassKind.OBJECT;
350                case CLASS_OBJECT:
351                    return ClassKind.CLASS_OBJECT;
352            }
353            throw new IllegalArgumentException("Unknown class kind: " + kind);
354        }
355    
356        @NotNull
357        public List<DeserializedTypeParameterDescriptor> typeParameters(
358                @NotNull List<TypeParameter> protos,
359                @NotNull TypeDeserializer typeDeserializer
360        ) {
361            List<DeserializedTypeParameterDescriptor> result = new ArrayList<DeserializedTypeParameterDescriptor>(protos.size());
362            for (int i = 0; i < protos.size(); i++) {
363                TypeParameter proto = protos.get(i);
364                DeserializedTypeParameterDescriptor descriptor = new DeserializedTypeParameterDescriptor(
365                        storageManager,
366                        typeDeserializer,
367                        proto,
368                        containingDeclaration,
369                        nameResolver.getName(proto.getName()),
370                        variance(proto.getVariance()),
371                        proto.getReified(),
372                        i
373                );
374                result.add(descriptor);
375            }
376            return result;
377        }
378    
379        private static Variance variance(TypeParameter.Variance proto) {
380            switch (proto) {
381                case IN:
382                    return Variance.IN_VARIANCE;
383                case OUT:
384                    return Variance.OUT_VARIANCE;
385                case INV:
386                    return Variance.INVARIANT;
387            }
388            throw new IllegalStateException("Unknown projection: " + proto);
389        }
390    
391        @NotNull
392        private List<ValueParameterDescriptor> valueParameters(@NotNull Callable callable, @NotNull AnnotatedCallableKind kind) {
393            DeclarationDescriptor containerOfCallable = containingDeclaration.getContainingDeclaration();
394            assert containerOfCallable instanceof ClassOrPackageFragmentDescriptor
395                    : "Only members in classes or package fragments should be serialized: " + containerOfCallable;
396            ClassOrPackageFragmentDescriptor classOrPackage = (ClassOrPackageFragmentDescriptor) containerOfCallable;
397    
398            List<Callable.ValueParameter> protos = callable.getValueParameterList();
399            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
400            for (int i = 0; i < protos.size(); i++) {
401                Callable.ValueParameter proto = protos.get(i);
402                result.add(new ValueParameterDescriptorImpl(
403                        containingDeclaration,
404                        null,
405                        i,
406                        getAnnotations(classOrPackage, callable, kind, proto),
407                        nameResolver.getName(proto.getName()),
408                        typeDeserializer.type(proto.getType()),
409                        Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
410                        typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null))
411                );
412            }
413            return result;
414        }
415    
416        @NotNull
417        private Annotations getAnnotations(
418                @NotNull ClassOrPackageFragmentDescriptor classOrPackage,
419                @NotNull Callable callable,
420                @NotNull AnnotatedCallableKind kind,
421                @NotNull Callable.ValueParameter valueParameter
422        ) {
423            return Flags.HAS_ANNOTATIONS.get(valueParameter.getFlags())
424                   ? deserializers.getAnnotationDeserializer().loadValueParameterAnnotations(classOrPackage, callable, nameResolver, kind, valueParameter)
425                   : Annotations.EMPTY;
426        }
427    }