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