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.descriptors;
018    
019    import jet.Function0;
020    import jet.Function1;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.jet.descriptors.serialization.*;
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.OverridingUtil;
029    import org.jetbrains.jet.lang.resolve.name.Name;
030    import org.jetbrains.jet.lang.resolve.scopes.InnerClassesScopeWrapper;
031    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
032    import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
033    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
034    import org.jetbrains.jet.lang.types.ErrorUtils;
035    import org.jetbrains.jet.lang.types.JetType;
036    import org.jetbrains.jet.lang.types.TypeConstructor;
037    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
038    import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
039    import org.jetbrains.jet.storage.NotNullLazyValue;
040    import org.jetbrains.jet.storage.NullableLazyValue;
041    import org.jetbrains.jet.storage.StorageManager;
042    
043    import java.util.*;
044    
045    import static org.jetbrains.jet.descriptors.serialization.TypeDeserializer.TypeParameterResolver.NONE;
046    import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
047    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
048    
049    public class DeserializedClassDescriptor extends AbstractClassDescriptor implements ClassDescriptor {
050    
051        private final ClassId classId;
052        private final ProtoBuf.Class classProto;
053        private final TypeDeserializer typeDeserializer;
054        private final DescriptorDeserializer deserializer;
055        private final DeserializedMemberScope memberScope;
056        private final ReceiverParameterDescriptor thisAsReceiverParameter;
057    
058        private final NullableLazyValue<ConstructorDescriptor> primaryConstructor;
059    
060        private final AnnotationDeserializer annotationDeserializer;
061        private final NotNullLazyValue<List<AnnotationDescriptor>> annotations;
062    
063        private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
064    
065        private final NestedClassDescriptors nestedClasses;
066        private final NestedClassDescriptors nestedObjects;
067    
068        private final NotNullLazyValue<DeclarationDescriptor> containingDeclaration;
069        private final DeserializedClassTypeConstructor typeConstructor;
070        private final Modality modality;
071        private final Visibility visibility;
072        private final ClassKind kind;
073        private final boolean isInner;
074        private final InnerClassesScopeWrapper innerClassesScope;
075        private final DescriptorFinder descriptorFinder;
076    
077        public DeserializedClassDescriptor(
078                @NotNull StorageManager storageManager,
079                @NotNull AnnotationDeserializer annotationResolver,
080                @NotNull DescriptorFinder descriptorFinder,
081                @NotNull ClassData classData
082        ) {
083            super(classData.getNameResolver().getClassId(classData.getClassProto().getFqName()).getRelativeClassName().shortName());
084            NameResolver nameResolver = classData.getNameResolver();
085            this.classProto = classData.getClassProto();
086    
087            this.classId = nameResolver.getClassId(classProto.getFqName());
088            this.descriptorFinder = descriptorFinder;
089    
090            TypeDeserializer notNullTypeDeserializer = new TypeDeserializer(storageManager, null, nameResolver,
091                                                                            descriptorFinder, "Deserializer for class " + name, NONE);
092            DescriptorDeserializer outerDeserializer = DescriptorDeserializer.create(storageManager, notNullTypeDeserializer,
093                                                                                     this, nameResolver, annotationResolver);
094            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(classProto.getTypeParameterCount());
095            this.deserializer = outerDeserializer.createChildDeserializer(this, classProto.getTypeParameterList(), typeParameters);
096            this.typeDeserializer = deserializer.getTypeDeserializer();
097    
098            this.containingDeclaration = storageManager.createLazyValue(new Function0<DeclarationDescriptor>() {
099                @Override
100                public DeclarationDescriptor invoke() {
101                    return computeContainingDeclaration();
102                }
103            });
104    
105            this.typeConstructor = new DeserializedClassTypeConstructor(typeParameters);
106            this.memberScope = new DeserializedClassMemberScope(storageManager, this);
107            this.innerClassesScope = new InnerClassesScopeWrapper(memberScope);
108            this.thisAsReceiverParameter = new LazyClassReceiverParameterDescriptor();
109    
110            int flags = classProto.getFlags();
111            this.modality = DescriptorDeserializer.modality(Flags.MODALITY.get(flags));
112            this.visibility = DescriptorDeserializer.visibility(Flags.VISIBILITY.get(flags));
113            this.kind = DescriptorDeserializer.classKind(Flags.CLASS_KIND.get(flags));
114            this.isInner = Flags.INNER.get(flags);
115    
116            this.annotationDeserializer = annotationResolver;
117            this.annotations = storageManager.createLazyValue(new Function0<List<AnnotationDescriptor>>() {
118                @Override
119                public List<AnnotationDescriptor> invoke() {
120                    return computeAnnotations();
121                }
122            });
123    
124            this.primaryConstructor = storageManager.createNullableLazyValue(new Function0<ConstructorDescriptor>() {
125                @Override
126                public ConstructorDescriptor invoke() {
127                    return computePrimaryConstructor();
128                }
129            });
130    
131            this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptor>() {
132                @Override
133                public ClassDescriptor invoke() {
134                    return computeClassObjectDescriptor();
135                }
136            });
137            this.nestedClasses = new NestedClassDescriptors(storageManager, names(classProto.getNestedClassNameList(), nameResolver));
138            this.nestedObjects = new NestedClassDescriptors(storageManager, names(classProto.getNestedObjectNameList(), nameResolver));
139        }
140    
141        @NotNull
142        private static Set<Name> names(@NotNull List<Integer> nameIndices, @NotNull NameResolver nameResolver) {
143            Set<Name> result = new HashSet<Name>(nameIndices.size());
144            for (Integer index : nameIndices) {
145                result.add(nameResolver.getName(index));
146            }
147            return result;
148        }
149    
150        @NotNull
151        @Override
152        public DeclarationDescriptor getContainingDeclaration() {
153            return containingDeclaration.invoke();
154        }
155    
156        @NotNull
157        private DeclarationDescriptor computeContainingDeclaration() {
158            ClassOrNamespaceDescriptor result = classId.isTopLevelClass() ?
159                                                descriptorFinder.findPackage(classId.getPackageFqName()) :
160                                                descriptorFinder.findClass(classId.getOuterClassId());
161            return result != null ? result : ErrorUtils.getErrorModule();
162        }
163    
164        @NotNull
165        @Override
166        public TypeConstructor getTypeConstructor() {
167            return typeConstructor;
168        }
169    
170    
171        @NotNull
172        @Override
173        public ClassKind getKind() {
174            return kind;
175        }
176    
177        @NotNull
178        @Override
179        public Modality getModality() {
180            return modality;
181        }
182    
183        @NotNull
184        @Override
185        public Visibility getVisibility() {
186            return visibility;
187        }
188    
189        @Override
190        public boolean isInner() {
191            return isInner;
192        }
193    
194        private List<AnnotationDescriptor> computeAnnotations() {
195            if (!Flags.HAS_ANNOTATIONS.get(classProto.getFlags())) {
196                return Collections.emptyList();
197            }
198            return annotationDeserializer.loadClassAnnotations(this, classProto);
199        }
200    
201        @Override
202        public List<AnnotationDescriptor> getAnnotations() {
203            return annotations.invoke();
204        }
205    
206        @Override
207        protected JetScope getScopeForMemberLookup() {
208            return memberScope;
209        }
210    
211        @NotNull
212        @Override
213        public JetScope getUnsubstitutedInnerClassesScope() {
214            return innerClassesScope;
215        }
216    
217        @Nullable
218        private ConstructorDescriptor computePrimaryConstructor() {
219            if (!classProto.hasPrimaryConstructor()) return null;
220    
221            ProtoBuf.Callable constructorProto = classProto.getPrimaryConstructor();
222            return (ConstructorDescriptor) deserializer.loadCallable(constructorProto);
223        }
224    
225        @Nullable
226        @Override
227        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
228            return primaryConstructor.invoke();
229        }
230    
231        @NotNull
232        @Override
233        public Collection<ConstructorDescriptor> getConstructors() {
234            ConstructorDescriptor constructor = getUnsubstitutedPrimaryConstructor();
235            if (constructor == null) {
236                return Collections.emptyList();
237            }
238            // TODO: other constructors
239            return Collections.singletonList(constructor);
240        }
241    
242        @Nullable
243        @Override
244        public JetType getClassObjectType() {
245            ClassDescriptor classObjectDescriptor = getClassObjectDescriptor();
246            return classObjectDescriptor == null ? null : classObjectDescriptor.getDefaultType();
247        }
248    
249        @Nullable
250        private ClassDescriptor computeClassObjectDescriptor() {
251            if (!classProto.getClassObjectPresent()) {
252                return null;
253            }
254    
255            if (getKind() == ClassKind.ENUM_CLASS) {
256                MutableClassDescriptor classObject = createEnumClassObject();
257    
258                for (int enumEntry : classProto.getEnumEntryList()) {
259                    createEnumEntry(classObject, deserializer.getNameResolver().getName(enumEntry));
260                }
261    
262                return classObject;
263            }
264    
265            return descriptorFinder.findClass(classId.createNestedClassId(getClassObjectName(getName())));
266        }
267    
268        @NotNull
269        private MutableClassDescriptor createEnumClassObject() {
270            MutableClassDescriptor classObject = new MutableClassDescriptor(this, getScopeForMemberLookup(), ClassKind.CLASS_OBJECT,
271                                                                            false, getClassObjectName(getName()));
272            classObject.setModality(Modality.FINAL);
273            classObject.setVisibility(getVisibility());
274            classObject.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
275            classObject.createTypeConstructor();
276    
277            ConstructorDescriptorImpl primaryConstructor = DescriptorFactory.createPrimaryConstructorForObject(classObject);
278            primaryConstructor.setReturnType(classObject.getDefaultType());
279            classObject.setPrimaryConstructor(primaryConstructor);
280    
281            JetType defaultType = getDefaultType();
282            JetType defaultTypeArray = KotlinBuiltIns.getInstance().getArrayType(defaultType);
283            classObject.getBuilder().addFunctionDescriptor(
284                    DescriptorFactory.createEnumClassObjectValuesMethod(classObject, defaultTypeArray));
285            classObject.getBuilder().addFunctionDescriptor(
286                    DescriptorFactory.createEnumClassObjectValueOfMethod(classObject, defaultType));
287    
288            return classObject;
289        }
290    
291        private void createEnumEntry(@NotNull MutableClassDescriptor enumClassObject, @NotNull Name name) {
292            PropertyDescriptorImpl property = new PropertyDescriptorForObjectImpl(enumClassObject,
293                                                                                  Collections.<AnnotationDescriptor>emptyList(),
294                                                                                  Visibilities.PUBLIC, name, this);
295            property.setType(getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(),
296                             enumClassObject.getThisAsReceiverParameter(), NO_RECEIVER_PARAMETER);
297    
298            PropertyGetterDescriptorImpl getter = DescriptorFactory.createDefaultGetter(property);
299            getter.initialize(property.getReturnType());
300            property.initialize(getter, null);
301    
302            enumClassObject.getBuilder().addPropertyDescriptor(property);
303        }
304    
305        @Nullable
306        @Override
307        public ClassDescriptor getClassObjectDescriptor() {
308            return classObjectDescriptor.invoke();
309        }
310    
311        @NotNull
312        @Override
313        public ReceiverParameterDescriptor getThisAsReceiverParameter() {
314            return thisAsReceiverParameter;
315        }
316    
317        private Collection<JetType> computeSuperTypes() {
318            List<JetType> supertypes = new ArrayList<JetType>(classProto.getSupertypeCount());
319            for (ProtoBuf.Type supertype : classProto.getSupertypeList()) {
320                supertypes.add(typeDeserializer.type(supertype));
321            }
322            return supertypes;
323        }
324    
325        @Override
326        public String toString() {
327            return "deserialized class " + getName().toString();
328        }
329    
330        private class DeserializedClassTypeConstructor implements TypeConstructor {
331            private final Collection<JetType> supertypes = computeSuperTypes();
332            private final List<TypeParameterDescriptor> parameters;
333    
334            public DeserializedClassTypeConstructor(@NotNull List<TypeParameterDescriptor> typeParameters) {
335                parameters = typeParameters;
336            }
337    
338            @NotNull
339            @Override
340            public List<TypeParameterDescriptor> getParameters() {
341                return parameters;
342            }
343    
344            @NotNull
345            @Override
346            public Collection<JetType> getSupertypes() {
347                return supertypes;
348            }
349    
350            @Override
351            public boolean isFinal() {
352                return !getModality().isOverridable();
353            }
354    
355            @Override
356            public boolean isDenotable() {
357                return true;
358            }
359    
360            @Nullable
361            @Override
362            public ClassifierDescriptor getDeclarationDescriptor() {
363                return DeserializedClassDescriptor.this;
364            }
365    
366            @Override
367            public List<AnnotationDescriptor> getAnnotations() {
368                return Collections.emptyList(); // TODO
369            }
370    
371            @Override
372            public String toString() {
373                return getName().toString();
374            }
375        }
376    
377        private static class DeserializedClassMemberScope extends DeserializedMemberScope {
378            private final DeserializedClassDescriptor classDescriptor;
379    
380            public DeserializedClassMemberScope(@NotNull StorageManager storageManager, @NotNull DeserializedClassDescriptor classDescriptor) {
381                super(storageManager, classDescriptor, classDescriptor.deserializer, classDescriptor.classProto.getMemberList());
382                this.classDescriptor = classDescriptor;
383            }
384    
385            @Override
386            protected void computeNonDeclaredFunctions(
387                    @NotNull Name name, @NotNull Collection<FunctionDescriptor> functions
388            ) {
389                Collection<FunctionDescriptor> fromSupertypes = new ArrayList<FunctionDescriptor>();
390                for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
391                    fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
392                }
393                generateFakeOverrides(name, fromSupertypes, functions);
394            }
395    
396            @Override
397            protected void computeNonDeclaredProperties(
398                    @NotNull Name name, @NotNull Collection<PropertyDescriptor> property
399            ) {
400                Collection<PropertyDescriptor> fromSupertypes = new ArrayList<PropertyDescriptor>();
401                for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
402                    //noinspection unchecked
403                    fromSupertypes.addAll((Collection) supertype.getMemberScope().getProperties(name));
404                }
405                generateFakeOverrides(name, fromSupertypes, property);
406            }
407    
408            private <D extends CallableMemberDescriptor> void generateFakeOverrides(
409                    @NotNull Name name,
410                    @NotNull Collection<D> fromSupertypes,
411                    @NotNull final Collection<D> result
412            ) {
413                List<CallableMemberDescriptor> fromCurrent = new ArrayList<CallableMemberDescriptor>(result);
414                OverridingUtil.generateOverridesInFunctionGroup(
415                        name,
416                        fromSupertypes,
417                        fromCurrent,
418                        classDescriptor,
419                        new OverridingUtil.DescriptorSink() {
420                            @Override
421                            public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
422                                OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new OverridingUtil.NotInferredVisibilitySink() {
423                                    @Override
424                                    public void cannotInferVisibility(@NotNull CallableMemberDescriptor descriptor) {
425                                        // Do nothing
426                                        // TODO: do something
427                                    }
428                                });
429                                //noinspection unchecked
430                                result.add((D) fakeOverride);
431                            }
432    
433                            @Override
434                            public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
435                                // TODO report conflicts
436                            }
437                        }
438                );
439            }
440    
441            @Override
442            protected void addNonDeclaredDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
443                for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
444                    for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
445                        if (descriptor instanceof FunctionDescriptor) {
446                            result.addAll(getFunctions(descriptor.getName()));
447                        }
448                        else if (descriptor instanceof PropertyDescriptor) {
449                            result.addAll(getProperties(descriptor.getName()));
450                        }
451                        // Nothing else is inherited
452                    }
453                }
454            }
455    
456            @Nullable
457            @Override
458            protected ReceiverParameterDescriptor getImplicitReceiver() {
459                return classDescriptor.getThisAsReceiverParameter();
460            }
461    
462            @Nullable
463            @Override
464            protected ClassifierDescriptor getClassDescriptor(@NotNull Name name) {
465                return classDescriptor.nestedClasses.findClass.invoke(name);
466            }
467    
468            @Override
469            protected void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
470                result.addAll(classDescriptor.nestedClasses.getAllDescriptors());
471            }
472    
473            @Nullable
474            @Override
475            public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
476                return classDescriptor.nestedObjects.findClass.invoke(name);
477            }
478    
479            @NotNull
480            @Override
481            protected Collection<ClassDescriptor> computeAllObjectDescriptors() {
482                return classDescriptor.nestedObjects.getAllDescriptors();
483            }
484        }
485    
486        private class NestedClassDescriptors {
487            private final Set<Name> declaredNames;
488            private final MemoizedFunctionToNullable<Name, ClassDescriptor> findClass;
489    
490            public NestedClassDescriptors(@NotNull StorageManager storageManager, @NotNull Set<Name> declaredNames) {
491                this.declaredNames = declaredNames;
492                this.findClass = storageManager.createMemoizedFunctionWithNullableValues(new Function1<Name, ClassDescriptor>() {
493                    @Override
494                    public ClassDescriptor invoke(Name name) {
495                        return NestedClassDescriptors.this.declaredNames.contains(name) ?
496                               descriptorFinder.findClass(classId.createNestedClassId(name)) :
497                               null;
498                    }
499                });
500            }
501    
502            @NotNull
503            public Collection<ClassDescriptor> getAllDescriptors() {
504                Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(declaredNames.size());
505                for (Name name : declaredNames) {
506                    ClassDescriptor descriptor = findClass.invoke(name);
507                    if (descriptor != null) {
508                        result.add(descriptor);
509                    }
510                }
511                return result;
512            }
513        }
514    
515        private class LazyClassReceiverParameterDescriptor extends AbstractReceiverParameterDescriptor {
516            private final ClassReceiver classReceiver = new ClassReceiver(DeserializedClassDescriptor.this);
517    
518            @NotNull
519            @Override
520            public JetType getType() {
521                return getDefaultType();
522            }
523    
524            @NotNull
525            @Override
526            public ReceiverValue getValue() {
527                return classReceiver;
528            }
529    
530            @NotNull
531            @Override
532            public DeclarationDescriptor getContainingDeclaration() {
533                return DeserializedClassDescriptor.this;
534            }
535        }
536    }
537