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 kotlin.Function0;
020    import kotlin.Function1;
021    import kotlin.KotlinPackage;
022    import kotlin.Unit;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.descriptors.serialization.*;
026    import org.jetbrains.jet.lang.descriptors.*;
027    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
028    import org.jetbrains.jet.lang.descriptors.impl.AbstractClassDescriptor;
029    import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
030    import org.jetbrains.jet.lang.descriptors.impl.EnumEntrySyntheticClassDescriptor;
031    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
032    import org.jetbrains.jet.lang.resolve.DescriptorFactory;
033    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
034    import org.jetbrains.jet.lang.resolve.OverridingUtil;
035    import org.jetbrains.jet.lang.resolve.name.Name;
036    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
037    import org.jetbrains.jet.lang.types.ErrorUtils;
038    import org.jetbrains.jet.lang.types.JetType;
039    import org.jetbrains.jet.lang.types.TypeConstructor;
040    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
041    import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
042    import org.jetbrains.jet.storage.NotNullLazyValue;
043    import org.jetbrains.jet.storage.NullableLazyValue;
044    import org.jetbrains.jet.storage.StorageManager;
045    
046    import java.util.*;
047    
048    import static org.jetbrains.jet.descriptors.serialization.TypeDeserializer.TypeParameterResolver.NONE;
049    import static org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName;
050    
051    public class DeserializedClassDescriptor extends AbstractClassDescriptor implements ClassDescriptor {
052    
053        private final ClassId classId;
054        private final ProtoBuf.Class classProto;
055        private final StorageManager storageManager;
056        private final TypeDeserializer typeDeserializer;
057        private final DescriptorDeserializer deserializer;
058        private final DeserializedMemberScope memberScope;
059    
060        private final NullableLazyValue<ConstructorDescriptor> primaryConstructor;
061    
062        private final Deserializers deserializers;
063        private final NotNullLazyValue<Annotations> annotations;
064    
065        private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
066    
067        private final NestedClassDescriptors nestedClasses;
068    
069        private final NotNullLazyValue<DeclarationDescriptor> containingDeclaration;
070        private final DeserializedClassTypeConstructor typeConstructor;
071        private final Modality modality;
072        private final Visibility visibility;
073        private final ClassKind kind;
074        private final boolean isInner;
075        private final DescriptorFinder descriptorFinder;
076        private final PackageFragmentProvider packageFragmentProvider;
077    
078        public DeserializedClassDescriptor(
079                @NotNull StorageManager storageManager,
080                @NotNull Deserializers deserializers,
081                @NotNull DescriptorFinder descriptorFinder,
082                @NotNull PackageFragmentProvider packageFragmentProvider,
083                @NotNull NameResolver nameResolver,
084                @NotNull ProtoBuf.Class classProto
085        ) {
086            super(storageManager, nameResolver.getClassId(classProto.getFqName()).getRelativeClassName().shortName());
087            this.classProto = classProto;
088            this.classId = nameResolver.getClassId(classProto.getFqName());
089            this.storageManager = storageManager;
090            this.packageFragmentProvider = packageFragmentProvider;
091            this.descriptorFinder = descriptorFinder;
092    
093            TypeDeserializer notNullTypeDeserializer = new TypeDeserializer(storageManager, null, nameResolver,
094                                                                            descriptorFinder, "Deserializer for class " + getName(), NONE);
095            DescriptorDeserializer outerDeserializer = DescriptorDeserializer.create(storageManager, notNullTypeDeserializer,
096                                                                                     this, nameResolver, deserializers);
097            List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(classProto.getTypeParameterCount());
098            this.deserializer = outerDeserializer.createChildDeserializer(this, classProto.getTypeParameterList(), typeParameters);
099            this.typeDeserializer = deserializer.getTypeDeserializer();
100    
101            this.containingDeclaration = storageManager.createLazyValue(new Function0<DeclarationDescriptor>() {
102                @Override
103                public DeclarationDescriptor invoke() {
104                    return computeContainingDeclaration();
105                }
106            });
107    
108            this.typeConstructor = new DeserializedClassTypeConstructor(typeParameters);
109            this.memberScope = new DeserializedClassMemberScope(storageManager, this);
110    
111            int flags = classProto.getFlags();
112            this.modality = DescriptorDeserializer.modality(Flags.MODALITY.get(flags));
113            this.visibility = DescriptorDeserializer.visibility(Flags.VISIBILITY.get(flags));
114            this.kind = DescriptorDeserializer.classKind(Flags.CLASS_KIND.get(flags));
115            this.isInner = Flags.INNER.get(flags);
116    
117            this.deserializers = deserializers;
118            this.annotations = storageManager.createLazyValue(new Function0<Annotations>() {
119                @Override
120                public Annotations invoke() {
121                    return computeAnnotations();
122                }
123            });
124    
125            this.primaryConstructor = storageManager.createNullableLazyValue(new Function0<ConstructorDescriptor>() {
126                @Override
127                public ConstructorDescriptor invoke() {
128                    return computePrimaryConstructor();
129                }
130            });
131    
132            this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptor>() {
133                @Override
134                public ClassDescriptor invoke() {
135                    return computeClassObjectDescriptor();
136                }
137            });
138    
139            this.nestedClasses = new NestedClassDescriptors();
140        }
141    
142        @NotNull
143        @Override
144        public DeclarationDescriptor getContainingDeclaration() {
145            return containingDeclaration.invoke();
146        }
147    
148        @NotNull
149        private DeclarationDescriptor computeContainingDeclaration() {
150            if (classId.isTopLevelClass()) {
151                List<PackageFragmentDescriptor> fragments = packageFragmentProvider.getPackageFragments(classId.getPackageFqName());
152                assert fragments.size() == 1 : "there should be exactly one package: " + fragments;
153                return fragments.iterator().next();
154            }
155            else {
156                ClassOrPackageFragmentDescriptor result = descriptorFinder.findClass(classId.getOuterClassId());
157                return result != null ? result : ErrorUtils.getErrorModule();
158            }
159        }
160    
161        @NotNull
162        @Override
163        public TypeConstructor getTypeConstructor() {
164            return typeConstructor;
165        }
166    
167    
168        @NotNull
169        @Override
170        public ClassKind getKind() {
171            return kind;
172        }
173    
174        @NotNull
175        @Override
176        public Modality getModality() {
177            return modality;
178        }
179    
180        @NotNull
181        @Override
182        public Visibility getVisibility() {
183            return visibility;
184        }
185    
186        @Override
187        public boolean isInner() {
188            return isInner;
189        }
190    
191        private Annotations computeAnnotations() {
192            if (!Flags.HAS_ANNOTATIONS.get(classProto.getFlags())) {
193                return Annotations.EMPTY;
194            }
195            return deserializers.getAnnotationDeserializer().loadClassAnnotations(this, classProto);
196        }
197    
198        @NotNull
199        @Override
200        public Annotations getAnnotations() {
201            return annotations.invoke();
202        }
203    
204        @NotNull
205        @Override
206        protected JetScope getScopeForMemberLookup() {
207            return memberScope;
208        }
209    
210        @Nullable
211        private ConstructorDescriptor computePrimaryConstructor() {
212            if (!classProto.hasPrimaryConstructor()) return null;
213    
214            ProtoBuf.Class.PrimaryConstructor constructorProto = classProto.getPrimaryConstructor();
215            if (!constructorProto.hasData()) {
216                ConstructorDescriptorImpl descriptor = DescriptorFactory.createPrimaryConstructorForObject(this);
217                descriptor.setReturnType(getDefaultType());
218                return descriptor;
219            }
220    
221            return (ConstructorDescriptor) deserializer.loadCallable(constructorProto.getData());
222        }
223    
224        @Nullable
225        @Override
226        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
227            return primaryConstructor.invoke();
228        }
229    
230        @NotNull
231        @Override
232        public Collection<ConstructorDescriptor> getConstructors() {
233            ConstructorDescriptor constructor = getUnsubstitutedPrimaryConstructor();
234            if (constructor == null) {
235                return Collections.emptyList();
236            }
237            // TODO: other constructors
238            return Collections.singletonList(constructor);
239        }
240    
241        @Nullable
242        private ClassDescriptor computeClassObjectDescriptor() {
243            if (!classProto.hasClassObject()) {
244                return null;
245            }
246    
247            if (getKind() == ClassKind.ENUM_CLASS) {
248                return createEnumClassObject();
249            }
250    
251            if (getKind() == ClassKind.OBJECT) {
252                ProtoBuf.Class.ClassObject classObjectProto = classProto.getClassObject();
253                if (!classObjectProto.hasData()) {
254                    throw new IllegalStateException("Object should have a serialized class object: " + classId);
255                }
256    
257                return new DeserializedClassDescriptor(storageManager, deserializers, descriptorFinder, packageFragmentProvider,
258                                                       deserializer.getNameResolver(), classObjectProto.getData());
259            }
260    
261            return descriptorFinder.findClass(classId.createNestedClassId(getClassObjectName(getName())));
262        }
263    
264        @NotNull
265        private ClassDescriptorWithResolutionScopes createEnumClassObject() {
266            final MutableClassDescriptor classObject = new MutableClassDescriptor(this, getScopeForMemberLookup(), ClassKind.CLASS_OBJECT,
267                                                                                  false, getClassObjectName(getName()));
268            JetType supertype = KotlinBuiltIns.getInstance().getAnyType();
269            classObject.setSupertypes(Collections.singleton(supertype));
270            classObject.setModality(Modality.FINAL);
271            classObject.setVisibility(DescriptorUtils.getSyntheticClassObjectVisibility());
272            classObject.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
273            classObject.setPrimaryConstructor(DescriptorFactory.createPrimaryConstructorForObject(classObject));
274            classObject.createTypeConstructor();
275    
276            JetType enumType = getDefaultType();
277            JetType enumArrayType = KotlinBuiltIns.getInstance().getArrayType(enumType);
278            classObject.getBuilder().addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValuesMethod(classObject, enumArrayType));
279            classObject.getBuilder().addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValueOfMethod(classObject, enumType));
280    
281            OverridingUtil.DescriptorSink sink = new OverridingUtil.DescriptorSink() {
282                @Override
283                public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
284                    OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new Function1<CallableMemberDescriptor, Unit>() {
285                        @Override
286                        public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
287                            throw new IllegalStateException("Cannot infer visibility for " + descriptor + " in " + classObject);
288                        }
289                    });
290                    classObject.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
291                }
292    
293                @Override
294                public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
295                    throw new IllegalStateException("Conflict on enum class object override: " + fromSuper + " vs " + fromCurrent);
296                }
297            };
298    
299            JetScope superScope = supertype.getMemberScope();
300    
301            for (DeclarationDescriptor descriptor : superScope.getAllDescriptors()) {
302                if (descriptor instanceof FunctionDescriptor) {
303                    Name name = descriptor.getName();
304                    OverridingUtil.generateOverridesInFunctionGroup(name, superScope.getFunctions(name),
305                                                                    Collections.<FunctionDescriptor>emptySet(), classObject, sink);
306                }
307            }
308    
309            return classObject;
310        }
311    
312        @Nullable
313        @Override
314        public ClassDescriptor getClassObjectDescriptor() {
315            return classObjectDescriptor.invoke();
316        }
317    
318        private Collection<JetType> computeSuperTypes() {
319            List<JetType> supertypes = new ArrayList<JetType>(classProto.getSupertypeCount());
320            for (ProtoBuf.Type supertype : classProto.getSupertypeList()) {
321                supertypes.add(typeDeserializer.type(supertype));
322            }
323            return supertypes;
324        }
325    
326        @Override
327        public String toString() {
328            // not using descriptor render to preserve laziness
329            return "deserialized class " + getName().toString();
330        }
331    
332        private class DeserializedClassTypeConstructor implements TypeConstructor {
333            private final Collection<JetType> supertypes = computeSuperTypes();
334            private final List<TypeParameterDescriptor> parameters;
335    
336            public DeserializedClassTypeConstructor(@NotNull List<TypeParameterDescriptor> typeParameters) {
337                parameters = typeParameters;
338            }
339    
340            @NotNull
341            @Override
342            public List<TypeParameterDescriptor> getParameters() {
343                return parameters;
344            }
345    
346            @NotNull
347            @Override
348            public Collection<JetType> getSupertypes() {
349                // We cannot have error supertypes because subclasses inherit error functions from them
350                // Filtering right away means copying the list every time, so we check for the rare condition first, and only then filter
351                for (JetType supertype : supertypes) {
352                    if (supertype.isError()) {
353                        return KotlinPackage.filter(supertypes, new Function1<JetType, Boolean>() {
354                            @Override
355                            public Boolean invoke(JetType type) {
356                                return !type.isError();
357                            }
358                        });
359                    }
360                }
361                return supertypes;
362            }
363    
364            @Override
365            public boolean isFinal() {
366                return !getModality().isOverridable();
367            }
368    
369            @Override
370            public boolean isDenotable() {
371                return true;
372            }
373    
374            @Nullable
375            @Override
376            public ClassifierDescriptor getDeclarationDescriptor() {
377                return DeserializedClassDescriptor.this;
378            }
379    
380            @NotNull
381            @Override
382            public Annotations getAnnotations() {
383                return Annotations.EMPTY; // TODO
384            }
385    
386            @Override
387            public String toString() {
388                return getName().toString();
389            }
390        }
391    
392        private static class DeserializedClassMemberScope extends DeserializedMemberScope {
393            private final DeserializedClassDescriptor classDescriptor;
394    
395            public DeserializedClassMemberScope(@NotNull StorageManager storageManager, @NotNull DeserializedClassDescriptor classDescriptor) {
396                super(storageManager, classDescriptor, classDescriptor.deserializer, classDescriptor.classProto.getMemberList());
397                this.classDescriptor = classDescriptor;
398            }
399    
400            @Override
401            protected void computeNonDeclaredFunctions(
402                    @NotNull Name name, @NotNull Collection<FunctionDescriptor> functions
403            ) {
404                Collection<FunctionDescriptor> fromSupertypes = new ArrayList<FunctionDescriptor>();
405                for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
406                    fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
407                }
408                generateFakeOverrides(name, fromSupertypes, functions);
409            }
410    
411            @Override
412            protected void computeNonDeclaredProperties(
413                    @NotNull Name name, @NotNull Collection<PropertyDescriptor> property
414            ) {
415                Collection<PropertyDescriptor> fromSupertypes = new ArrayList<PropertyDescriptor>();
416                for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
417                    //noinspection unchecked
418                    fromSupertypes.addAll((Collection) supertype.getMemberScope().getProperties(name));
419                }
420                generateFakeOverrides(name, fromSupertypes, property);
421            }
422    
423            private <D extends CallableMemberDescriptor> void generateFakeOverrides(
424                    @NotNull Name name,
425                    @NotNull Collection<D> fromSupertypes,
426                    @NotNull final Collection<D> result
427            ) {
428                List<CallableMemberDescriptor> fromCurrent = new ArrayList<CallableMemberDescriptor>(result);
429                OverridingUtil.generateOverridesInFunctionGroup(
430                        name,
431                        fromSupertypes,
432                        fromCurrent,
433                        classDescriptor,
434                        new OverridingUtil.DescriptorSink() {
435                            @Override
436                            public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
437                                OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new Function1<CallableMemberDescriptor, Unit>() {
438                                    @Override
439                                    public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
440                                        // Do nothing
441                                        // TODO: do something
442                                        return Unit.VALUE;
443                                    }
444                                });
445                                //noinspection unchecked
446                                result.add((D) fakeOverride);
447                            }
448    
449                            @Override
450                            public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
451                                // TODO report conflicts
452                            }
453                        }
454                );
455            }
456    
457            @Override
458            protected void addNonDeclaredDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
459                for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
460                    for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
461                        if (descriptor instanceof FunctionDescriptor) {
462                            result.addAll(getFunctions(descriptor.getName()));
463                        }
464                        else if (descriptor instanceof PropertyDescriptor) {
465                            result.addAll(getProperties(descriptor.getName()));
466                        }
467                        // Nothing else is inherited
468                    }
469                }
470            }
471    
472            @Nullable
473            @Override
474            protected ReceiverParameterDescriptor getImplicitReceiver() {
475                return classDescriptor.getThisAsReceiverParameter();
476            }
477    
478            @Nullable
479            @Override
480            protected ClassifierDescriptor getClassDescriptor(@NotNull Name name) {
481                return classDescriptor.nestedClasses.findClass.invoke(name);
482            }
483    
484            @Override
485            protected void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
486                result.addAll(classDescriptor.nestedClasses.getAllDescriptors());
487            }
488        }
489    
490        private class NestedClassDescriptors {
491            private final Set<Name> nestedClassNames;
492            private final MemoizedFunctionToNullable<Name, ClassDescriptor> findClass;
493            private final Set<Name> enumEntryNames;
494    
495            public NestedClassDescriptors() {
496                this.nestedClassNames = nestedClassNames();
497                this.enumEntryNames = enumEntryNames();
498    
499                final NotNullLazyValue<Collection<Name>> enumMemberNames = storageManager.createLazyValue(new Function0<Collection<Name>>() {
500                    @Override
501                    public Collection<Name> invoke() {
502                        return computeEnumMemberNames();
503                    }
504                });
505    
506                this.findClass = storageManager.createMemoizedFunctionWithNullableValues(new Function1<Name, ClassDescriptor>() {
507                    @Override
508                    public ClassDescriptor invoke(Name name) {
509                        if (enumEntryNames.contains(name)) {
510                            return EnumEntrySyntheticClassDescriptor
511                                    .create(storageManager, DeserializedClassDescriptor.this, name, enumMemberNames);
512                        }
513                        if (nestedClassNames.contains(name)) {
514                            return descriptorFinder.findClass(classId.createNestedClassId(name));
515                        }
516                        return null;
517                    }
518                });
519            }
520    
521            @NotNull
522            private Set<Name> nestedClassNames() {
523                Set<Name> result = new HashSet<Name>();
524                NameResolver nameResolver = deserializer.getNameResolver();
525                for (Integer index : classProto.getNestedClassNameList()) {
526                    result.add(nameResolver.getName(index));
527                }
528                return result;
529            }
530    
531            @NotNull
532            private Set<Name> enumEntryNames() {
533                if (getKind() != ClassKind.ENUM_CLASS) {
534                    return Collections.emptySet();
535                }
536    
537                Set<Name> result = new HashSet<Name>();
538                NameResolver nameResolver = deserializer.getNameResolver();
539                for (Integer index : classProto.getEnumEntryList()) {
540                    result.add(nameResolver.getName(index));
541                }
542                return result;
543            }
544    
545            @NotNull
546            private Collection<Name> computeEnumMemberNames() {
547                Collection<Name> result = new HashSet<Name>();
548    
549                for (JetType supertype : getTypeConstructor().getSupertypes()) {
550                    for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
551                        if (descriptor instanceof SimpleFunctionDescriptor || descriptor instanceof PropertyDescriptor) {
552                            result.add(descriptor.getName());
553                        }
554                    }
555                }
556    
557                final NameResolver nameResolver = deserializer.getNameResolver();
558                return KotlinPackage.mapTo(classProto.getMemberList(), result, new Function1<ProtoBuf.Callable, Name>() {
559                    @Override
560                    public Name invoke(@NotNull ProtoBuf.Callable callable) {
561                        return nameResolver.getName(callable.getName());
562                    }
563                });
564            }
565    
566            @NotNull
567            public Collection<ClassDescriptor> getAllDescriptors() {
568                Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(nestedClassNames.size() + enumEntryNames.size());
569                for (Name name : nestedClassNames) {
570                    ClassDescriptor descriptor = findClass.invoke(name);
571                    if (descriptor != null) {
572                        result.add(descriptor);
573                    }
574                }
575                for (Name name : enumEntryNames) {
576                    ClassDescriptor descriptor = findClass.invoke(name);
577                    if (descriptor != null) {
578                        result.add(descriptor);
579                    }
580                }
581                return result;
582            }
583        }
584    }